forked from qt-creator/qt-creator
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:
@@ -28,10 +28,12 @@ namespace Sqlite {
|
|||||||
|
|
||||||
using NanotraceHR::keyValue;
|
using NanotraceHR::keyValue;
|
||||||
|
|
||||||
BaseStatement::BaseStatement(Utils::SmallStringView sqlStatement, Database &database)
|
BaseStatement::BaseStatement(Utils::SmallStringView sqlStatement,
|
||||||
|
Database &database,
|
||||||
|
const source_location &sourceLocation)
|
||||||
: m_database(database)
|
: m_database(database)
|
||||||
{
|
{
|
||||||
prepare(sqlStatement);
|
prepare(sqlStatement, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
class UnlockNotification
|
class UnlockNotification
|
||||||
@@ -67,15 +69,15 @@ private:
|
|||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
void BaseStatement::waitForUnlockNotify() const
|
void BaseStatement::waitForUnlockNotify(const source_location &sourceLocation) const
|
||||||
{
|
{
|
||||||
UnlockNotification unlockNotification;
|
UnlockNotification unlockNotification;
|
||||||
int resultCode = sqlite3_unlock_notify(sqliteDatabaseHandle(),
|
int resultCode = sqlite3_unlock_notify(sqliteDatabaseHandle(sourceLocation),
|
||||||
UnlockNotification::unlockNotifyCallBack,
|
UnlockNotification::unlockNotifyCallBack,
|
||||||
&unlockNotification);
|
&unlockNotification);
|
||||||
|
|
||||||
if (resultCode == SQLITE_LOCKED)
|
if (resultCode == SQLITE_LOCKED)
|
||||||
throw DeadLock();
|
throw DeadLock(sourceLocation);
|
||||||
|
|
||||||
unlockNotification.wait();
|
unlockNotification.wait();
|
||||||
}
|
}
|
||||||
@@ -89,7 +91,7 @@ void BaseStatement::reset() const noexcept
|
|||||||
sqlite3_reset(m_compiledStatement.get());
|
sqlite3_reset(m_compiledStatement.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseStatement::next() const
|
bool BaseStatement::next(const source_location &sourceLocation) const
|
||||||
{
|
{
|
||||||
NanotraceHR::Tracer tracer{"next",
|
NanotraceHR::Tracer tracer{"next",
|
||||||
sqliteLowLevelCategory(),
|
sqliteLowLevelCategory(),
|
||||||
@@ -99,7 +101,7 @@ bool BaseStatement::next() const
|
|||||||
do {
|
do {
|
||||||
resultCode = sqlite3_step(m_compiledStatement.get());
|
resultCode = sqlite3_step(m_compiledStatement.get());
|
||||||
if (resultCode == SQLITE_LOCKED) {
|
if (resultCode == SQLITE_LOCKED) {
|
||||||
waitForUnlockNotify();
|
waitForUnlockNotify(sourceLocation);
|
||||||
sqlite3_reset(m_compiledStatement.get());
|
sqlite3_reset(m_compiledStatement.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,15 +112,15 @@ bool BaseStatement::next() const
|
|||||||
else if (resultCode == SQLITE_DONE)
|
else if (resultCode == SQLITE_DONE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Sqlite::throwError(resultCode, sqliteDatabaseHandle());
|
Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseStatement::step() const
|
void BaseStatement::step(const source_location &sourceLocation) const
|
||||||
{
|
{
|
||||||
next();
|
next(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseStatement::bindNull(int index)
|
void BaseStatement::bindNull(int index, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
NanotraceHR::Tracer tracer{"bind null",
|
NanotraceHR::Tracer tracer{"bind null",
|
||||||
sqliteLowLevelCategory(),
|
sqliteLowLevelCategory(),
|
||||||
@@ -127,15 +129,15 @@ void BaseStatement::bindNull(int index)
|
|||||||
|
|
||||||
int resultCode = sqlite3_bind_null(m_compiledStatement.get(), index);
|
int resultCode = sqlite3_bind_null(m_compiledStatement.get(), index);
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
Sqlite::throwError(resultCode, sqliteDatabaseHandle());
|
Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseStatement::bind(int index, NullValue)
|
void BaseStatement::bind(int index, NullValue, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
bindNull(index);
|
bindNull(index, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseStatement::bind(int index, int value)
|
void BaseStatement::bind(int index, int value, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
NanotraceHR::Tracer tracer{"bind int",
|
NanotraceHR::Tracer tracer{"bind int",
|
||||||
sqliteLowLevelCategory(),
|
sqliteLowLevelCategory(),
|
||||||
@@ -145,10 +147,10 @@ void BaseStatement::bind(int index, int value)
|
|||||||
|
|
||||||
int resultCode = sqlite3_bind_int(m_compiledStatement.get(), index, value);
|
int resultCode = sqlite3_bind_int(m_compiledStatement.get(), index, value);
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
Sqlite::throwError(resultCode, sqliteDatabaseHandle());
|
Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseStatement::bind(int index, long long value)
|
void BaseStatement::bind(int index, long long value, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
NanotraceHR::Tracer tracer{"bind long long",
|
NanotraceHR::Tracer tracer{"bind long long",
|
||||||
sqliteLowLevelCategory(),
|
sqliteLowLevelCategory(),
|
||||||
@@ -158,10 +160,10 @@ void BaseStatement::bind(int index, long long value)
|
|||||||
|
|
||||||
int resultCode = sqlite3_bind_int64(m_compiledStatement.get(), index, value);
|
int resultCode = sqlite3_bind_int64(m_compiledStatement.get(), index, value);
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
Sqlite::throwError(resultCode, sqliteDatabaseHandle());
|
Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseStatement::bind(int index, double value)
|
void BaseStatement::bind(int index, double value, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
NanotraceHR::Tracer tracer{"bind double",
|
NanotraceHR::Tracer tracer{"bind double",
|
||||||
sqliteLowLevelCategory(),
|
sqliteLowLevelCategory(),
|
||||||
@@ -171,10 +173,10 @@ void BaseStatement::bind(int index, double value)
|
|||||||
|
|
||||||
int resultCode = sqlite3_bind_double(m_compiledStatement.get(), index, value);
|
int resultCode = sqlite3_bind_double(m_compiledStatement.get(), index, value);
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
Sqlite::throwError(resultCode, sqliteDatabaseHandle());
|
Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseStatement::bind(int index, void *pointer)
|
void BaseStatement::bind(int index, void *pointer, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
NanotraceHR::Tracer tracer{"bind pointer",
|
NanotraceHR::Tracer tracer{"bind pointer",
|
||||||
sqliteLowLevelCategory(),
|
sqliteLowLevelCategory(),
|
||||||
@@ -184,10 +186,10 @@ void BaseStatement::bind(int index, void *pointer)
|
|||||||
|
|
||||||
int resultCode = sqlite3_bind_pointer(m_compiledStatement.get(), index, pointer, "carray", nullptr);
|
int resultCode = sqlite3_bind_pointer(m_compiledStatement.get(), index, pointer, "carray", nullptr);
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
Sqlite::throwError(resultCode, sqliteDatabaseHandle());
|
Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseStatement::bind(int index, Utils::span<const int> values)
|
void BaseStatement::bind(int index, Utils::span<const int> values, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
NanotraceHR::Tracer tracer{"bind int span",
|
NanotraceHR::Tracer tracer{"bind int span",
|
||||||
sqliteLowLevelCategory(),
|
sqliteLowLevelCategory(),
|
||||||
@@ -203,10 +205,12 @@ void BaseStatement::bind(int index, Utils::span<const int> values)
|
|||||||
CARRAY_INT32,
|
CARRAY_INT32,
|
||||||
SQLITE_STATIC);
|
SQLITE_STATIC);
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
Sqlite::throwError(resultCode, sqliteDatabaseHandle());
|
Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseStatement::bind(int index, Utils::span<const long long> values)
|
void BaseStatement::bind(int index,
|
||||||
|
Utils::span<const long long> values,
|
||||||
|
const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
NanotraceHR::Tracer tracer{"bind long long span",
|
NanotraceHR::Tracer tracer{"bind long long span",
|
||||||
sqliteLowLevelCategory(),
|
sqliteLowLevelCategory(),
|
||||||
@@ -222,10 +226,12 @@ void BaseStatement::bind(int index, Utils::span<const long long> values)
|
|||||||
CARRAY_INT64,
|
CARRAY_INT64,
|
||||||
SQLITE_STATIC);
|
SQLITE_STATIC);
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
Sqlite::throwError(resultCode, sqliteDatabaseHandle());
|
Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseStatement::bind(int index, Utils::span<const double> values)
|
void BaseStatement::bind(int index,
|
||||||
|
Utils::span<const double> values,
|
||||||
|
const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
NanotraceHR::Tracer tracer{"bind double span",
|
NanotraceHR::Tracer tracer{"bind double span",
|
||||||
sqliteLowLevelCategory(),
|
sqliteLowLevelCategory(),
|
||||||
@@ -241,10 +247,12 @@ void BaseStatement::bind(int index, Utils::span<const double> values)
|
|||||||
CARRAY_DOUBLE,
|
CARRAY_DOUBLE,
|
||||||
SQLITE_STATIC);
|
SQLITE_STATIC);
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
Sqlite::throwError(resultCode, sqliteDatabaseHandle());
|
Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseStatement::bind(int index, Utils::span<const char *> values)
|
void BaseStatement::bind(int index,
|
||||||
|
Utils::span<const char *> values,
|
||||||
|
const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
NanotraceHR::Tracer tracer{"bind const char* span",
|
NanotraceHR::Tracer tracer{"bind const char* span",
|
||||||
sqliteLowLevelCategory(),
|
sqliteLowLevelCategory(),
|
||||||
@@ -260,10 +268,10 @@ void BaseStatement::bind(int index, Utils::span<const char *> values)
|
|||||||
CARRAY_TEXT,
|
CARRAY_TEXT,
|
||||||
SQLITE_STATIC);
|
SQLITE_STATIC);
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
Sqlite::throwError(resultCode, sqliteDatabaseHandle());
|
Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseStatement::bind(int index, Utils::SmallStringView text)
|
void BaseStatement::bind(int index, Utils::SmallStringView text, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
NanotraceHR::Tracer tracer{"bind string",
|
NanotraceHR::Tracer tracer{"bind string",
|
||||||
sqliteLowLevelCategory(),
|
sqliteLowLevelCategory(),
|
||||||
@@ -277,10 +285,10 @@ void BaseStatement::bind(int index, Utils::SmallStringView text)
|
|||||||
int(text.size()),
|
int(text.size()),
|
||||||
SQLITE_STATIC);
|
SQLITE_STATIC);
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
Sqlite::throwError(resultCode, sqliteDatabaseHandle());
|
Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseStatement::bind(int index, BlobView blobView)
|
void BaseStatement::bind(int index, BlobView blobView, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
NanotraceHR::Tracer tracer{"bind blob",
|
NanotraceHR::Tracer tracer{"bind blob",
|
||||||
sqliteLowLevelCategory(),
|
sqliteLowLevelCategory(),
|
||||||
@@ -302,10 +310,10 @@ void BaseStatement::bind(int index, BlobView blobView)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
Sqlite::throwError(resultCode, sqliteDatabaseHandle());
|
Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseStatement::bind(int index, const Value &value)
|
void BaseStatement::bind(int index, const Value &value, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
NanotraceHR::Tracer tracer{
|
NanotraceHR::Tracer tracer{
|
||||||
"bind value",
|
"bind value",
|
||||||
@@ -315,24 +323,24 @@ void BaseStatement::bind(int index, const Value &value)
|
|||||||
|
|
||||||
switch (value.type()) {
|
switch (value.type()) {
|
||||||
case ValueType::Integer:
|
case ValueType::Integer:
|
||||||
bind(index, value.toInteger());
|
bind(index, value.toInteger(), sourceLocation);
|
||||||
break;
|
break;
|
||||||
case ValueType::Float:
|
case ValueType::Float:
|
||||||
bind(index, value.toFloat());
|
bind(index, value.toFloat(), sourceLocation);
|
||||||
break;
|
break;
|
||||||
case ValueType::String:
|
case ValueType::String:
|
||||||
bind(index, value.toStringView());
|
bind(index, value.toStringView(), sourceLocation);
|
||||||
break;
|
break;
|
||||||
case ValueType::Blob:
|
case ValueType::Blob:
|
||||||
bind(index, value.toBlobView());
|
bind(index, value.toBlobView(), sourceLocation);
|
||||||
break;
|
break;
|
||||||
case ValueType::Null:
|
case ValueType::Null:
|
||||||
bind(index, NullValue{});
|
bind(index, NullValue{}, sourceLocation);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseStatement::bind(int index, ValueView value)
|
void BaseStatement::bind(int index, ValueView value, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
NanotraceHR::Tracer tracer{
|
NanotraceHR::Tracer tracer{
|
||||||
"bind value",
|
"bind value",
|
||||||
@@ -342,37 +350,37 @@ void BaseStatement::bind(int index, ValueView value)
|
|||||||
|
|
||||||
switch (value.type()) {
|
switch (value.type()) {
|
||||||
case ValueType::Integer:
|
case ValueType::Integer:
|
||||||
bind(index, value.toInteger());
|
bind(index, value.toInteger(), sourceLocation);
|
||||||
break;
|
break;
|
||||||
case ValueType::Float:
|
case ValueType::Float:
|
||||||
bind(index, value.toFloat());
|
bind(index, value.toFloat(), sourceLocation);
|
||||||
break;
|
break;
|
||||||
case ValueType::String:
|
case ValueType::String:
|
||||||
bind(index, value.toStringView());
|
bind(index, value.toStringView(), sourceLocation);
|
||||||
break;
|
break;
|
||||||
case ValueType::Blob:
|
case ValueType::Blob:
|
||||||
bind(index, value.toBlobView());
|
bind(index, value.toBlobView(), sourceLocation);
|
||||||
break;
|
break;
|
||||||
case ValueType::Null:
|
case ValueType::Null:
|
||||||
bind(index, NullValue{});
|
bind(index, NullValue{}, sourceLocation);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseStatement::prepare(Utils::SmallStringView sqlStatement)
|
void BaseStatement::prepare(Utils::SmallStringView sqlStatement, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
NanotraceHR::Tracer tracer{"prepare",
|
NanotraceHR::Tracer tracer{"prepare",
|
||||||
sqliteLowLevelCategory(),
|
sqliteLowLevelCategory(),
|
||||||
keyValue("sql statement", sqlStatement)};
|
keyValue("sql statement", sqlStatement)};
|
||||||
|
|
||||||
if (!m_database.isLocked())
|
if (!m_database.isLocked())
|
||||||
throw DatabaseIsNotLocked{};
|
throw DatabaseIsNotLocked{sourceLocation};
|
||||||
|
|
||||||
int resultCode;
|
int resultCode;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
sqlite3_stmt *sqliteStatement = nullptr;
|
sqlite3_stmt *sqliteStatement = nullptr;
|
||||||
resultCode = sqlite3_prepare_v2(sqliteDatabaseHandle(),
|
resultCode = sqlite3_prepare_v2(sqliteDatabaseHandle(sourceLocation),
|
||||||
sqlStatement.data(),
|
sqlStatement.data(),
|
||||||
int(sqlStatement.size()),
|
int(sqlStatement.size()),
|
||||||
&sqliteStatement,
|
&sqliteStatement,
|
||||||
@@ -381,33 +389,34 @@ void BaseStatement::prepare(Utils::SmallStringView sqlStatement)
|
|||||||
|
|
||||||
if (resultCode == SQLITE_LOCKED) {
|
if (resultCode == SQLITE_LOCKED) {
|
||||||
tracer.tick("wait for unlock");
|
tracer.tick("wait for unlock");
|
||||||
waitForUnlockNotify();
|
waitForUnlockNotify(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
} while (resultCode == SQLITE_LOCKED);
|
} while (resultCode == SQLITE_LOCKED);
|
||||||
|
|
||||||
|
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
Sqlite::throwError(resultCode, sqliteDatabaseHandle());
|
Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
|
||||||
|
|
||||||
tracer.end(keyValue("sqlite statement", handle()));
|
tracer.end(keyValue("sqlite statement", handle()));
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite3 *BaseStatement::sqliteDatabaseHandle() const
|
sqlite3 *BaseStatement::sqliteDatabaseHandle(const source_location &sourceLocation) const
|
||||||
{
|
{
|
||||||
return m_database.backend().sqliteDatabaseHandle();
|
return m_database.backend().sqliteDatabaseHandle(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseStatement::checkBindingParameterCount(int bindingParameterCount) const
|
void BaseStatement::checkBindingParameterCount(int bindingParameterCount,
|
||||||
|
const source_location &sourceLocation) const
|
||||||
{
|
{
|
||||||
if (bindingParameterCount != sqlite3_bind_parameter_count(m_compiledStatement.get()))
|
if (bindingParameterCount != sqlite3_bind_parameter_count(m_compiledStatement.get()))
|
||||||
throw WrongBindingParameterCount{};
|
throw WrongBindingParameterCount{sourceLocation};
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseStatement::checkColumnCount(int columnCount) const
|
void BaseStatement::checkColumnCount(int columnCount, const source_location &sourceLocation) const
|
||||||
{
|
{
|
||||||
if (columnCount != sqlite3_column_count(m_compiledStatement.get()))
|
if (columnCount != sqlite3_column_count(m_compiledStatement.get()))
|
||||||
throw WrongColumnCount{};
|
throw WrongColumnCount{sourceLocation};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseStatement::isReadOnlyStatement() const
|
bool BaseStatement::isReadOnlyStatement() const
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
#include "sqlite3_fwd.h"
|
#include "sqlite3_fwd.h"
|
||||||
#include "sqliteglobal.h"
|
#include "sqliteglobal.h"
|
||||||
|
|
||||||
|
#include "sourcelocation.h"
|
||||||
#include "sqliteblob.h"
|
#include "sqliteblob.h"
|
||||||
#include "sqliteexception.h"
|
#include "sqliteexception.h"
|
||||||
#include "sqliteids.h"
|
#include "sqliteids.h"
|
||||||
@@ -41,14 +42,16 @@ class SQLITE_EXPORT BaseStatement
|
|||||||
public:
|
public:
|
||||||
using Database = ::Sqlite::Database;
|
using Database = ::Sqlite::Database;
|
||||||
|
|
||||||
explicit BaseStatement(Utils::SmallStringView sqlStatement, Database &database);
|
explicit BaseStatement(Utils::SmallStringView sqlStatement,
|
||||||
|
Database &database,
|
||||||
|
const source_location &sourceLocation);
|
||||||
|
|
||||||
BaseStatement(const BaseStatement &) = delete;
|
BaseStatement(const BaseStatement &) = delete;
|
||||||
BaseStatement &operator=(const BaseStatement &) = delete;
|
BaseStatement &operator=(const BaseStatement &) = delete;
|
||||||
BaseStatement(BaseStatement &&) = default;
|
BaseStatement(BaseStatement &&) = default;
|
||||||
|
|
||||||
bool next() const;
|
bool next(const source_location &sourceLocation) const;
|
||||||
void step() const;
|
void step(const source_location &sourceLocation) const;
|
||||||
void reset() const noexcept;
|
void reset() const noexcept;
|
||||||
|
|
||||||
Type fetchType(int column) const;
|
Type fetchType(int column) const;
|
||||||
@@ -62,52 +65,56 @@ public:
|
|||||||
template<typename Type>
|
template<typename Type>
|
||||||
Type fetchValue(int column) const;
|
Type fetchValue(int column) const;
|
||||||
|
|
||||||
void bindNull(int index);
|
void bindNull(int index, const source_location &sourceLocation);
|
||||||
void bind(int index, NullValue);
|
void bind(int index, NullValue, const source_location &sourceLocation);
|
||||||
void bind(int index, int value);
|
void bind(int index, int value, const source_location &sourceLocation);
|
||||||
void bind(int index, long long value);
|
void bind(int index, long long value, const source_location &sourceLocation);
|
||||||
void bind(int index, double value);
|
void bind(int index, double value, const source_location &sourceLocation);
|
||||||
void bind(int index, void *pointer);
|
void bind(int index, void *pointer, const source_location &sourceLocation);
|
||||||
void bind(int index, Utils::span<const int> values);
|
void bind(int index, Utils::span<const int> values, const source_location &sourceLocation);
|
||||||
void bind(int index, Utils::span<const long long> values);
|
void bind(int index, Utils::span<const long long> values, const source_location &sourceLocation);
|
||||||
void bind(int index, Utils::span<const double> values);
|
void bind(int index, Utils::span<const double> values, const source_location &sourceLocation);
|
||||||
void bind(int index, Utils::span<const char *> values);
|
void bind(int index, Utils::span<const char *> values, const source_location &sourceLocation);
|
||||||
void bind(int index, Utils::SmallStringView value);
|
void bind(int index, Utils::SmallStringView value, const source_location &sourceLocation);
|
||||||
void bind(int index, const Value &value);
|
void bind(int index, const Value &value, const source_location &sourceLocation);
|
||||||
void bind(int index, ValueView value);
|
void bind(int index, ValueView value, const source_location &sourceLocation);
|
||||||
void bind(int index, BlobView blobView);
|
void bind(int index, BlobView blobView, const source_location &sourceLocation);
|
||||||
|
|
||||||
template<typename Type, typename std::enable_if_t<Type::IsBasicId::value, bool> = true>
|
template<typename Type, typename std::enable_if_t<Type::IsBasicId::value, bool> = true>
|
||||||
void bind(int index, Type id)
|
void bind(int index, Type id, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
if (!id.isNull())
|
if (!id.isNull())
|
||||||
bind(index, id.internalId());
|
bind(index, id.internalId(), sourceLocation);
|
||||||
else
|
else
|
||||||
bindNull(index);
|
bindNull(index, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Enumeration, std::enable_if_t<std::is_enum_v<Enumeration>, bool> = true>
|
template<typename Enumeration, std::enable_if_t<std::is_enum_v<Enumeration>, bool> = true>
|
||||||
void bind(int index, Enumeration enumeration)
|
void bind(int index, Enumeration enumeration, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
bind(index, Utils::to_underlying(enumeration));
|
bind(index, Utils::to_underlying(enumeration), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bind(int index, uint value) { bind(index, static_cast<long long>(value)); }
|
void bind(int index, uint value, const source_location &sourceLocation)
|
||||||
|
|
||||||
void bind(int index, long value)
|
|
||||||
{
|
{
|
||||||
bind(index, static_cast<long long>(value));
|
bind(index, static_cast<long long>(value), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepare(Utils::SmallStringView sqlStatement);
|
void bind(int index, long value, const source_location &sourceLocation)
|
||||||
void waitForUnlockNotify() const;
|
{
|
||||||
|
bind(index, static_cast<long long>(value), sourceLocation);
|
||||||
|
}
|
||||||
|
|
||||||
sqlite3 *sqliteDatabaseHandle() const;
|
void prepare(Utils::SmallStringView sqlStatement, const source_location &sourceLocation);
|
||||||
|
void waitForUnlockNotify(const source_location &sourceLocation) const;
|
||||||
|
|
||||||
|
sqlite3 *sqliteDatabaseHandle(const source_location &sourceLocation) const;
|
||||||
|
|
||||||
void setIfIsReadyToFetchValues(int resultCode) const;
|
void setIfIsReadyToFetchValues(int resultCode) const;
|
||||||
void checkBindingName(int index) const;
|
void checkBindingName(int index) const;
|
||||||
void checkBindingParameterCount(int bindingParameterCount) const;
|
void checkBindingParameterCount(int bindingParameterCount,
|
||||||
void checkColumnCount(int columnCount) const;
|
const source_location &sourceLocation) const;
|
||||||
|
void checkColumnCount(int columnCount, const source_location &sourceLocation) const;
|
||||||
bool isReadOnlyStatement() const;
|
bool isReadOnlyStatement() const;
|
||||||
|
|
||||||
QString columnName(int column) const;
|
QString columnName(int column) const;
|
||||||
@@ -150,7 +157,7 @@ public:
|
|||||||
using BaseStatement::BaseStatement;
|
using BaseStatement::BaseStatement;
|
||||||
StatementImplementation(StatementImplementation &&) = default;
|
StatementImplementation(StatementImplementation &&) = default;
|
||||||
|
|
||||||
void execute()
|
void execute(const source_location &sourceLocation = source_location::current())
|
||||||
{
|
{
|
||||||
using NanotraceHR::keyValue;
|
using NanotraceHR::keyValue;
|
||||||
NanotraceHR::Tracer tracer{
|
NanotraceHR::Tracer tracer{
|
||||||
@@ -160,11 +167,11 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
Resetter resetter{this};
|
Resetter resetter{this};
|
||||||
BaseStatement::next();
|
BaseStatement::next(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... ValueType>
|
template<typename... ValueType>
|
||||||
void bindValues(const ValueType &...values)
|
void bindValues(const source_location &sourceLocation, const ValueType &...values)
|
||||||
{
|
{
|
||||||
using NanotraceHR::keyValue;
|
using NanotraceHR::keyValue;
|
||||||
NanotraceHR::Tracer tracer{"bind",
|
NanotraceHR::Tracer tracer{"bind",
|
||||||
@@ -174,11 +181,11 @@ public:
|
|||||||
static_assert(BindParameterCount == sizeof...(values), "Wrong binding parameter count!");
|
static_assert(BindParameterCount == sizeof...(values), "Wrong binding parameter count!");
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
(BaseStatement::bind(++index, values), ...);
|
(BaseStatement::bind(++index, values, sourceLocation), ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... ValueType>
|
template<typename... ValueType>
|
||||||
void write(const ValueType&... values)
|
void write(const source_location &sourceLocation, const ValueType &...values)
|
||||||
{
|
{
|
||||||
using NanotraceHR::keyValue;
|
using NanotraceHR::keyValue;
|
||||||
NanotraceHR::Tracer tracer{"write",
|
NanotraceHR::Tracer tracer{"write",
|
||||||
@@ -186,8 +193,15 @@ public:
|
|||||||
keyValue("sqlite statement", BaseStatement::handle())};
|
keyValue("sqlite statement", BaseStatement::handle())};
|
||||||
|
|
||||||
Resetter resetter{this};
|
Resetter resetter{this};
|
||||||
bindValues(values...);
|
bindValues(sourceLocation, values...);
|
||||||
BaseStatement::next();
|
BaseStatement::next(sourceLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... ValueType>
|
||||||
|
void write(const ValueType &...values)
|
||||||
|
{
|
||||||
|
static constexpr auto sourceLocation = source_location::current();
|
||||||
|
write(sourceLocation, values...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -213,9 +227,9 @@ public:
|
|||||||
|
|
||||||
template<typename Container,
|
template<typename Container,
|
||||||
std::size_t capacity = 32,
|
std::size_t capacity = 32,
|
||||||
typename = std::enable_if_t<is_container<Container>::value>,
|
typename std::enable_if_t<is_container<Container>::value, bool> = true,
|
||||||
typename... QueryTypes>
|
typename... QueryTypes>
|
||||||
auto values(const QueryTypes &...queryValues)
|
auto values(const source_location &sourceLocation, const QueryTypes &...queryValues)
|
||||||
{
|
{
|
||||||
using NanotraceHR::keyValue;
|
using NanotraceHR::keyValue;
|
||||||
NanotraceHR::Tracer tracer{"values",
|
NanotraceHR::Tracer tracer{"values",
|
||||||
@@ -228,9 +242,9 @@ public:
|
|||||||
if constexpr (!is_small_container<Container>::value)
|
if constexpr (!is_small_container<Container>::value)
|
||||||
resultValues.reserve(static_cast<size_tupe>(std::max(capacity, m_maximumResultCount)));
|
resultValues.reserve(static_cast<size_tupe>(std::max(capacity, m_maximumResultCount)));
|
||||||
|
|
||||||
bindValues(queryValues...);
|
bindValues(sourceLocation, queryValues...);
|
||||||
|
|
||||||
while (BaseStatement::next())
|
while (BaseStatement::next(sourceLocation))
|
||||||
emplaceBackValues(resultValues);
|
emplaceBackValues(resultValues);
|
||||||
|
|
||||||
setMaximumResultCount(static_cast<std::size_t>(resultValues.size()));
|
setMaximumResultCount(static_cast<std::size_t>(resultValues.size()));
|
||||||
@@ -238,18 +252,39 @@ public:
|
|||||||
return resultValues;
|
return resultValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ResultType,
|
template<typename Container,
|
||||||
std::size_t capacity = 32,
|
std::size_t capacity = 32,
|
||||||
template<typename...> typename Container = std::vector,
|
typename std::enable_if_t<is_container<Container>::value, bool> = true,
|
||||||
typename = std::enable_if_t<!is_container<ResultType>::value>,
|
|
||||||
typename... QueryTypes>
|
typename... QueryTypes>
|
||||||
auto values(const QueryTypes &...queryValues)
|
auto values(const QueryTypes &...queryValues)
|
||||||
{
|
{
|
||||||
return values<Container<ResultType>, capacity>(queryValues...);
|
static constexpr auto sourceLocation = source_location::current();
|
||||||
|
return value<Container, capacity>(sourceLocation, queryValues...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ResultType,
|
||||||
|
std::size_t capacity = 32,
|
||||||
|
template<typename...> typename Container = std::vector,
|
||||||
|
typename std::enable_if_t<!is_container<ResultType>::value, bool> = true,
|
||||||
|
typename... QueryTypes>
|
||||||
|
auto values(const source_location &sourceLocation, const QueryTypes &...queryValues)
|
||||||
|
{
|
||||||
|
return values<Container<ResultType>, capacity>(sourceLocation, queryValues...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ResultType,
|
||||||
|
std::size_t capacity = 32,
|
||||||
|
template<typename...> typename Container = std::vector,
|
||||||
|
typename std::enable_if_t<!is_container<ResultType>::value, bool> = true,
|
||||||
|
typename... QueryTypes>
|
||||||
|
auto values(const QueryTypes &...queryValues)
|
||||||
|
{
|
||||||
|
static constexpr auto sourceLocation = source_location::current();
|
||||||
|
return values<ResultType, capacity, Container>(sourceLocation, queryValues...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ResultType, typename... QueryTypes>
|
template<typename ResultType, typename... QueryTypes>
|
||||||
auto value(const QueryTypes &...queryValues)
|
auto value(const source_location &sourceLocation, const QueryTypes &...queryValues)
|
||||||
{
|
{
|
||||||
using NanotraceHR::keyValue;
|
using NanotraceHR::keyValue;
|
||||||
NanotraceHR::Tracer tracer{"value",
|
NanotraceHR::Tracer tracer{"value",
|
||||||
@@ -259,16 +294,23 @@ public:
|
|||||||
Resetter resetter{this};
|
Resetter resetter{this};
|
||||||
ResultType resultValue{};
|
ResultType resultValue{};
|
||||||
|
|
||||||
bindValues(queryValues...);
|
bindValues(sourceLocation, queryValues...);
|
||||||
|
|
||||||
if (BaseStatement::next())
|
if (BaseStatement::next(sourceLocation))
|
||||||
resultValue = createValue<ResultType>();
|
resultValue = createValue<ResultType>();
|
||||||
|
|
||||||
return resultValue;
|
return resultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ResultType, typename... QueryTypes>
|
template<typename ResultType, typename... QueryTypes>
|
||||||
auto optionalValue(const QueryTypes &...queryValues)
|
auto value(const QueryTypes &...queryValues)
|
||||||
|
{
|
||||||
|
static constexpr auto sourceLocation = source_location::current();
|
||||||
|
return value<ResultType>(sourceLocation, queryValues...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ResultType, typename... QueryTypes>
|
||||||
|
auto optionalValue(const source_location &sourceLocation, const QueryTypes &...queryValues)
|
||||||
{
|
{
|
||||||
using NanotraceHR::keyValue;
|
using NanotraceHR::keyValue;
|
||||||
NanotraceHR::Tracer tracer{"optionalValue",
|
NanotraceHR::Tracer tracer{"optionalValue",
|
||||||
@@ -278,31 +320,42 @@ public:
|
|||||||
Resetter resetter{this};
|
Resetter resetter{this};
|
||||||
std::optional<ResultType> resultValue;
|
std::optional<ResultType> resultValue;
|
||||||
|
|
||||||
bindValues(queryValues...);
|
bindValues(sourceLocation, queryValues...);
|
||||||
|
|
||||||
if (BaseStatement::next())
|
if (BaseStatement::next(sourceLocation))
|
||||||
resultValue = createOptionalValue<std::optional<ResultType>>();
|
resultValue = createOptionalValue<std::optional<ResultType>>();
|
||||||
|
|
||||||
return resultValue;
|
return resultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename ResultType, typename... QueryTypes>
|
||||||
|
auto optionalValue(const QueryTypes &...queryValues)
|
||||||
|
{
|
||||||
|
static constexpr auto sourceLocation = source_location::current();
|
||||||
|
return optionalValue<ResultType>(sourceLocation, queryValues...);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
static auto toValue(Utils::SmallStringView sqlStatement, Database &database)
|
static auto toValue(Utils::SmallStringView sqlStatement,
|
||||||
|
Database &database,
|
||||||
|
const source_location &sourceLocation = source_location::current())
|
||||||
{
|
{
|
||||||
using NanotraceHR::keyValue;
|
using NanotraceHR::keyValue;
|
||||||
NanotraceHR::Tracer tracer{"toValue", sqliteHighLevelCategory()};
|
NanotraceHR::Tracer tracer{"toValue", sqliteHighLevelCategory()};
|
||||||
|
|
||||||
StatementImplementation statement(sqlStatement, database);
|
StatementImplementation statement(sqlStatement, database, sourceLocation);
|
||||||
|
|
||||||
statement.checkColumnCount(1);
|
statement.checkColumnCount(1, sourceLocation);
|
||||||
|
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
return statement.template fetchValue<Type>(0);
|
return statement.template fetchValue<Type>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Callable, typename... QueryTypes>
|
template<typename Callable, typename... QueryTypes>
|
||||||
void readCallback(Callable &&callable, const QueryTypes &...queryValues)
|
void readCallback(Callable &&callable,
|
||||||
|
const source_location &sourceLocation,
|
||||||
|
const QueryTypes &...queryValues)
|
||||||
{
|
{
|
||||||
using NanotraceHR::keyValue;
|
using NanotraceHR::keyValue;
|
||||||
NanotraceHR::Tracer tracer{"readCallback",
|
NanotraceHR::Tracer tracer{"readCallback",
|
||||||
@@ -311,9 +364,9 @@ public:
|
|||||||
|
|
||||||
Resetter resetter{this};
|
Resetter resetter{this};
|
||||||
|
|
||||||
bindValues(queryValues...);
|
bindValues(sourceLocation, queryValues...);
|
||||||
|
|
||||||
while (BaseStatement::next()) {
|
while (BaseStatement::next(sourceLocation)) {
|
||||||
auto control = callCallable(callable);
|
auto control = callCallable(callable);
|
||||||
|
|
||||||
if (control == CallbackControl::Abort)
|
if (control == CallbackControl::Abort)
|
||||||
@@ -321,8 +374,17 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Callable, typename... QueryTypes>
|
||||||
|
void readCallback(Callable &&callable, const QueryTypes &...queryValues)
|
||||||
|
{
|
||||||
|
static constexpr auto sourceLocation = source_location::current();
|
||||||
|
readCallback(callable, sourceLocation, queryValues...);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Container, typename... QueryTypes>
|
template<typename Container, typename... QueryTypes>
|
||||||
void readTo(Container &container, const QueryTypes &...queryValues)
|
void readTo(Container &container,
|
||||||
|
const source_location &sourceLocation,
|
||||||
|
const QueryTypes &...queryValues)
|
||||||
{
|
{
|
||||||
using NanotraceHR::keyValue;
|
using NanotraceHR::keyValue;
|
||||||
NanotraceHR::Tracer tracer{"readTo",
|
NanotraceHR::Tracer tracer{"readTo",
|
||||||
@@ -331,22 +393,43 @@ public:
|
|||||||
|
|
||||||
Resetter resetter{this};
|
Resetter resetter{this};
|
||||||
|
|
||||||
bindValues(queryValues...);
|
bindValues(sourceLocation, queryValues...);
|
||||||
|
|
||||||
while (BaseStatement::next())
|
while (BaseStatement::next(sourceLocation))
|
||||||
emplaceBackValues(container);
|
emplaceBackValues(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Container, typename... QueryTypes>
|
||||||
|
void readTo(Container &container, const QueryTypes &...queryValues)
|
||||||
|
{
|
||||||
|
static constexpr auto sourceLocation = source_location::current();
|
||||||
|
readTo(container, sourceLocation, queryValues...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ResultType, typename... QueryTypes>
|
||||||
|
auto range(const source_location &sourceLocation, const QueryTypes &...queryValues)
|
||||||
|
{
|
||||||
|
return SqliteResultRange<ResultType>{*this, sourceLocation, queryValues...};
|
||||||
|
}
|
||||||
|
|
||||||
template<typename ResultType, typename... QueryTypes>
|
template<typename ResultType, typename... QueryTypes>
|
||||||
auto range(const QueryTypes &...queryValues)
|
auto range(const QueryTypes &...queryValues)
|
||||||
{
|
{
|
||||||
return SqliteResultRange<ResultType>{*this, queryValues...};
|
static constexpr auto sourceLocation = source_location::current();
|
||||||
|
return SqliteResultRange<ResultType>{*this, sourceLocation, queryValues...};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ResultType, typename... QueryTypes>
|
||||||
|
auto rangeWithTransaction(const source_location &sourceLocation, const QueryTypes &...queryValues)
|
||||||
|
{
|
||||||
|
return SqliteResultRangeWithTransaction<ResultType>{*this, sourceLocation, queryValues...};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ResultType, typename... QueryTypes>
|
template<typename ResultType, typename... QueryTypes>
|
||||||
auto rangeWithTransaction(const QueryTypes &...queryValues)
|
auto rangeWithTransaction(const QueryTypes &...queryValues)
|
||||||
{
|
{
|
||||||
return SqliteResultRangeWithTransaction<ResultType>{*this, queryValues...};
|
static constexpr auto sourceLocation = source_location::current();
|
||||||
|
return SqliteResultRangeWithTransaction<ResultType>{*this, sourceLocation, queryValues...};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ResultType>
|
template<typename ResultType>
|
||||||
@@ -362,23 +445,28 @@ public:
|
|||||||
using pointer = ResultType *;
|
using pointer = ResultType *;
|
||||||
using reference = ResultType &;
|
using reference = ResultType &;
|
||||||
|
|
||||||
SqliteResultIteratator(StatementImplementation &statement)
|
SqliteResultIteratator(StatementImplementation &statement,
|
||||||
|
const source_location &sourceLocation)
|
||||||
: m_statement{statement}
|
: m_statement{statement}
|
||||||
, m_hasNext{m_statement.next()}
|
, m_sourceLocation{sourceLocation}
|
||||||
|
, m_hasNext{m_statement.next(sourceLocation)}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
SqliteResultIteratator(StatementImplementation &statement, bool hasNext)
|
SqliteResultIteratator(StatementImplementation &statement,
|
||||||
|
const source_location &sourceLocation,
|
||||||
|
bool hasNext)
|
||||||
: m_statement{statement}
|
: m_statement{statement}
|
||||||
|
, m_sourceLocation{sourceLocation}
|
||||||
, m_hasNext{hasNext}
|
, m_hasNext{hasNext}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
SqliteResultIteratator &operator++()
|
SqliteResultIteratator &operator++()
|
||||||
{
|
{
|
||||||
m_hasNext = m_statement.next();
|
m_hasNext = m_statement.next(m_sourceLocation);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator++(int) { m_hasNext = m_statement.next(); }
|
void operator++(int) { m_hasNext = m_statement.next(m_sourceLocation); }
|
||||||
|
|
||||||
friend bool operator==(const SqliteResultIteratator &first,
|
friend bool operator==(const SqliteResultIteratator &first,
|
||||||
const SqliteResultIteratator &second)
|
const SqliteResultIteratator &second)
|
||||||
@@ -396,6 +484,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
StatementImplementation &m_statement;
|
StatementImplementation &m_statement;
|
||||||
|
const source_location &m_sourceLocation;
|
||||||
bool m_hasNext = false;
|
bool m_hasNext = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -404,8 +493,9 @@ public:
|
|||||||
using const_iterator = iterator;
|
using const_iterator = iterator;
|
||||||
|
|
||||||
template<typename... QueryTypes>
|
template<typename... QueryTypes>
|
||||||
BaseSqliteResultRange(StatementImplementation &statement)
|
BaseSqliteResultRange(StatementImplementation &statement, const source_location &sourceLocation)
|
||||||
: m_statement{statement}
|
: m_statement{statement}
|
||||||
|
, m_sourceLocation{sourceLocation}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,8 +503,9 @@ public:
|
|||||||
BaseSqliteResultRange &operator=(BaseSqliteResultRange &) = delete;
|
BaseSqliteResultRange &operator=(BaseSqliteResultRange &) = delete;
|
||||||
BaseSqliteResultRange &operator=(BaseSqliteResultRange &&) = delete;
|
BaseSqliteResultRange &operator=(BaseSqliteResultRange &&) = delete;
|
||||||
|
|
||||||
iterator begin() & { return iterator{m_statement}; }
|
iterator begin() & { return iterator{m_statement, m_sourceLocation}; }
|
||||||
iterator end() & { return iterator{m_statement, false}; }
|
|
||||||
|
iterator end() & { return iterator{m_statement, m_sourceLocation, false}; }
|
||||||
|
|
||||||
const_iterator begin() const & { return iterator{m_statement}; }
|
const_iterator begin() const & { return iterator{m_statement}; }
|
||||||
const_iterator end() const & { return iterator{m_statement, false}; }
|
const_iterator end() const & { return iterator{m_statement, false}; }
|
||||||
@@ -422,6 +513,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
using TracerCategory = std::decay_t<decltype(sqliteHighLevelCategory())>;
|
using TracerCategory = std::decay_t<decltype(sqliteHighLevelCategory())>;
|
||||||
StatementImplementation &m_statement;
|
StatementImplementation &m_statement;
|
||||||
|
const source_location &m_sourceLocation;
|
||||||
NanotraceHR::Tracer<TracerCategory, typename TracerCategory::IsActive> tracer{
|
NanotraceHR::Tracer<TracerCategory, typename TracerCategory::IsActive> tracer{
|
||||||
"range",
|
"range",
|
||||||
sqliteHighLevelCategory(),
|
sqliteHighLevelCategory(),
|
||||||
@@ -433,11 +525,13 @@ public:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template<typename... QueryTypes>
|
template<typename... QueryTypes>
|
||||||
SqliteResultRange(StatementImplementation &statement, const QueryTypes &...queryValues)
|
SqliteResultRange(StatementImplementation &statement,
|
||||||
: BaseSqliteResultRange<ResultType>{statement}
|
const source_location &sourceLocation,
|
||||||
|
const QueryTypes &...queryValues)
|
||||||
|
: BaseSqliteResultRange<ResultType>{statement, sourceLocation}
|
||||||
, resetter{&statement}
|
, resetter{&statement}
|
||||||
{
|
{
|
||||||
statement.bindValues(queryValues...);
|
statement.bindValues(sourceLocation, queryValues...);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -450,12 +544,14 @@ public:
|
|||||||
public:
|
public:
|
||||||
template<typename... QueryTypes>
|
template<typename... QueryTypes>
|
||||||
SqliteResultRangeWithTransaction(StatementImplementation &statement,
|
SqliteResultRangeWithTransaction(StatementImplementation &statement,
|
||||||
|
const source_location &sourceLocation,
|
||||||
const QueryTypes &...queryValues)
|
const QueryTypes &...queryValues)
|
||||||
: BaseSqliteResultRange<ResultType>{statement}
|
: BaseSqliteResultRange<ResultType>{statement, sourceLocation}
|
||||||
, m_transaction{statement.database()}
|
, m_transaction{statement.database(), sourceLocation}
|
||||||
, resetter{&statement}
|
, resetter{&statement}
|
||||||
|
, sourceLocation{sourceLocation}
|
||||||
{
|
{
|
||||||
statement.bindValues(queryValues...);
|
statement.bindValues(sourceLocation, queryValues...);
|
||||||
}
|
}
|
||||||
|
|
||||||
~SqliteResultRangeWithTransaction()
|
~SqliteResultRangeWithTransaction()
|
||||||
@@ -463,13 +559,14 @@ public:
|
|||||||
resetter.reset();
|
resetter.reset();
|
||||||
|
|
||||||
if (!std::uncaught_exceptions()) {
|
if (!std::uncaught_exceptions()) {
|
||||||
m_transaction.commit();
|
m_transaction.commit(sourceLocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DeferredTransaction<typename BaseStatement::Database> m_transaction;
|
DeferredTransaction<typename BaseStatement::Database> m_transaction;
|
||||||
Resetter resetter;
|
Resetter resetter;
|
||||||
|
source_location sourceLocation;
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@@ -19,34 +19,40 @@ namespace Sqlite {
|
|||||||
class Database::Statements
|
class Database::Statements
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Statements(Database &database)
|
Statements(Database &database, const source_location &sourceLocation)
|
||||||
: database(database)
|
: database(database)
|
||||||
|
, sourceLocation(sourceLocation)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Database &database;
|
Database &database;
|
||||||
ReadWriteStatement<> deferredBegin{"BEGIN", database};
|
source_location sourceLocation;
|
||||||
ReadWriteStatement<> immediateBegin{"BEGIN IMMEDIATE", database};
|
ReadWriteStatement<> deferredBegin{"BEGIN", database, sourceLocation};
|
||||||
ReadWriteStatement<> exclusiveBegin{"BEGIN EXCLUSIVE", database};
|
ReadWriteStatement<> immediateBegin{"BEGIN IMMEDIATE", database, sourceLocation};
|
||||||
ReadWriteStatement<> commitBegin{"COMMIT", database};
|
ReadWriteStatement<> exclusiveBegin{"BEGIN EXCLUSIVE", database, sourceLocation};
|
||||||
ReadWriteStatement<> rollbackBegin{"ROLLBACK", database};
|
ReadWriteStatement<> commitBegin{"COMMIT", database, sourceLocation};
|
||||||
|
ReadWriteStatement<> rollbackBegin{"ROLLBACK", database, sourceLocation};
|
||||||
Sessions sessions{database, "main", "databaseSessions"};
|
Sessions sessions{database, "main", "databaseSessions"};
|
||||||
};
|
};
|
||||||
|
|
||||||
Database::Database()
|
Database::Database(const source_location &sourceLocation)
|
||||||
: m_databaseBackend(*this)
|
: m_databaseBackend(*this, sourceLocation)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Database::Database(Utils::PathString databaseFilePath, JournalMode journalMode, LockingMode lockingMode)
|
Database::Database(Utils::PathString databaseFilePath,
|
||||||
: Database{std::move(databaseFilePath), 0ms, journalMode, lockingMode}
|
JournalMode journalMode,
|
||||||
|
LockingMode lockingMode,
|
||||||
|
const source_location &sourceLocation)
|
||||||
|
: Database{std::move(databaseFilePath), 0ms, journalMode, lockingMode, sourceLocation}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Database::Database(Utils::PathString databaseFilePath,
|
Database::Database(Utils::PathString databaseFilePath,
|
||||||
std::chrono::milliseconds busyTimeout,
|
std::chrono::milliseconds busyTimeout,
|
||||||
JournalMode journalMode,
|
JournalMode journalMode,
|
||||||
LockingMode lockingMode)
|
LockingMode lockingMode,
|
||||||
: m_databaseBackend(*this)
|
const source_location &sourceLocation)
|
||||||
|
: m_databaseBackend(*this, sourceLocation)
|
||||||
, m_busyTimeout(busyTimeout)
|
, m_busyTimeout(busyTimeout)
|
||||||
{
|
{
|
||||||
std::lock_guard lock{*this};
|
std::lock_guard lock{*this};
|
||||||
@@ -62,36 +68,38 @@ Database::Database(Utils::PathString databaseFilePath,
|
|||||||
|
|
||||||
Database::~Database() = default;
|
Database::~Database() = default;
|
||||||
|
|
||||||
void Database::activateLogging()
|
void Database::activateLogging(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
DatabaseBackend::activateLogging();
|
DatabaseBackend::activateLogging(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::open(LockingMode lockingMode)
|
void Database::open(LockingMode lockingMode, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
m_databaseBackend.open(m_databaseFilePath, m_openMode, m_journalMode);
|
m_databaseBackend.open(m_databaseFilePath, m_openMode, m_journalMode, sourceLocation);
|
||||||
if (m_busyTimeout > 0ms)
|
if (m_busyTimeout > 0ms)
|
||||||
m_databaseBackend.setBusyTimeout(m_busyTimeout);
|
m_databaseBackend.setBusyTimeout(m_busyTimeout);
|
||||||
else
|
else
|
||||||
m_databaseBackend.registerBusyHandler();
|
m_databaseBackend.registerBusyHandler(sourceLocation);
|
||||||
m_databaseBackend.setLockingMode(lockingMode);
|
m_databaseBackend.setLockingMode(lockingMode, sourceLocation);
|
||||||
m_databaseBackend.setJournalMode(m_journalMode);
|
m_databaseBackend.setJournalMode(m_journalMode, sourceLocation);
|
||||||
registerTransactionStatements();
|
registerTransactionStatements(sourceLocation);
|
||||||
m_isOpen = true;
|
m_isOpen = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::open(Utils::PathString &&databaseFilePath, LockingMode lockingMode)
|
void Database::open(Utils::PathString &&databaseFilePath,
|
||||||
|
LockingMode lockingMode,
|
||||||
|
const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
m_isInitialized = QFileInfo::exists(QString(databaseFilePath));
|
m_isInitialized = QFileInfo::exists(QString(databaseFilePath));
|
||||||
setDatabaseFilePath(std::move(databaseFilePath));
|
setDatabaseFilePath(std::move(databaseFilePath));
|
||||||
open(lockingMode);
|
open(lockingMode, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::close()
|
void Database::close(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
m_isOpen = false;
|
m_isOpen = false;
|
||||||
deleteTransactionStatements();
|
deleteTransactionStatements();
|
||||||
m_databaseBackend.close();
|
m_databaseBackend.close(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Database::isInitialized() const
|
bool Database::isInitialized() const
|
||||||
@@ -124,9 +132,9 @@ void Database::applyAndUpdateSessions()
|
|||||||
m_statements->sessions.applyAndUpdateSessions();
|
m_statements->sessions.applyAndUpdateSessions();
|
||||||
}
|
}
|
||||||
|
|
||||||
SessionChangeSets Database::changeSets() const
|
SessionChangeSets Database::changeSets(const source_location &sourceLocation) const
|
||||||
{
|
{
|
||||||
return m_statements->sessions.changeSets();
|
return m_statements->sessions.changeSets(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Utils::PathString &Database::databaseFilePath() const
|
const Utils::PathString &Database::databaseFilePath() const
|
||||||
@@ -144,9 +152,9 @@ JournalMode Database::journalMode() const
|
|||||||
return m_journalMode;
|
return m_journalMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
LockingMode Database::lockingMode() const
|
LockingMode Database::lockingMode(const source_location &sourceLocation) const
|
||||||
{
|
{
|
||||||
return m_databaseBackend.lockingMode();
|
return m_databaseBackend.lockingMode(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::setOpenMode(OpenMode openMode)
|
void Database::setOpenMode(OpenMode openMode)
|
||||||
@@ -159,14 +167,14 @@ OpenMode Database::openMode() const
|
|||||||
return m_openMode;
|
return m_openMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::execute(Utils::SmallStringView sqlStatement)
|
void Database::execute(Utils::SmallStringView sqlStatement, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
m_databaseBackend.execute(sqlStatement);
|
m_databaseBackend.execute(sqlStatement, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::registerTransactionStatements()
|
void Database::registerTransactionStatements(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
m_statements = std::make_unique<Statements>(*this);
|
m_statements = std::make_unique<Statements>(*this, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::deleteTransactionStatements()
|
void Database::deleteTransactionStatements()
|
||||||
@@ -174,68 +182,70 @@ void Database::deleteTransactionStatements()
|
|||||||
m_statements.reset();
|
m_statements.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::deferredBegin()
|
void Database::deferredBegin(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
m_statements->deferredBegin.execute();
|
m_statements->deferredBegin.execute(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::immediateBegin()
|
void Database::immediateBegin(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
m_statements->immediateBegin.execute();
|
m_statements->immediateBegin.execute(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::exclusiveBegin()
|
void Database::exclusiveBegin(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
m_statements->exclusiveBegin.execute();
|
m_statements->exclusiveBegin.execute(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::commit()
|
void Database::commit(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
m_statements->commitBegin.execute();
|
m_statements->commitBegin.execute(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::rollback()
|
void Database::rollback(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
m_statements->rollbackBegin.execute();
|
m_statements->rollbackBegin.execute(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::immediateSessionBegin()
|
void Database::immediateSessionBegin(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
m_statements->immediateBegin.execute();
|
m_statements->immediateBegin.execute(sourceLocation);
|
||||||
m_statements->sessions.create();
|
m_statements->sessions.create(sourceLocation);
|
||||||
}
|
}
|
||||||
void Database::sessionCommit()
|
|
||||||
|
void Database::sessionCommit(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
m_statements->sessions.commit();
|
m_statements->sessions.commit(sourceLocation);
|
||||||
m_statements->commitBegin.execute();
|
m_statements->commitBegin.execute(sourceLocation);
|
||||||
}
|
}
|
||||||
void Database::sessionRollback()
|
|
||||||
|
void Database::sessionRollback(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
m_statements->sessions.rollback();
|
m_statements->sessions.rollback();
|
||||||
m_statements->rollbackBegin.execute();
|
m_statements->rollbackBegin.execute(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::resetDatabaseForTestsOnly()
|
void Database::resetDatabaseForTestsOnly(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
m_databaseBackend.resetDatabaseForTestsOnly();
|
m_databaseBackend.resetDatabaseForTestsOnly(sourceLocation);
|
||||||
setIsInitialized(false);
|
setIsInitialized(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::clearAllTablesForTestsOnly()
|
void Database::clearAllTablesForTestsOnly(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
m_databaseBackend.disableForeignKeys();
|
m_databaseBackend.disableForeignKeys(sourceLocation);
|
||||||
{
|
{
|
||||||
Sqlite::ImmediateTransaction transaction{*this};
|
Sqlite::ImmediateTransaction transaction{*this, sourceLocation};
|
||||||
|
|
||||||
ReadStatement<1> tablesStatement{"SELECT name FROM sqlite_schema WHERE type='table'", *this};
|
ReadStatement<1> tablesStatement{"SELECT name FROM sqlite_schema WHERE type='table'", *this};
|
||||||
auto tables = tablesStatement.template values<Utils::SmallString>();
|
auto tables = tablesStatement.template values<Utils::SmallString>(sourceLocation);
|
||||||
for (const auto &table : tables)
|
for (const auto &table : tables)
|
||||||
execute("DELETE FROM " + table);
|
execute("DELETE FROM " + table, sourceLocation);
|
||||||
|
|
||||||
transaction.commit();
|
transaction.commit(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_databaseBackend.enableForeignKeys();
|
m_databaseBackend.enableForeignKeys(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
DatabaseBackend &Database::backend()
|
DatabaseBackend &Database::backend()
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "sourcelocation.h"
|
||||||
#include "sqlitedatabasebackend.h"
|
#include "sqlitedatabasebackend.h"
|
||||||
#include "sqlitedatabaseinterface.h"
|
#include "sqlitedatabaseinterface.h"
|
||||||
#include "sqliteglobal.h"
|
#include "sqliteglobal.h"
|
||||||
@@ -46,24 +47,29 @@ public:
|
|||||||
using ReadWriteStatement = Sqlite::ReadWriteStatement<ResultCount, BindParameterCount>;
|
using ReadWriteStatement = Sqlite::ReadWriteStatement<ResultCount, BindParameterCount>;
|
||||||
using BusyHandler = DatabaseBackend::BusyHandler;
|
using BusyHandler = DatabaseBackend::BusyHandler;
|
||||||
|
|
||||||
Database();
|
Database(const source_location &sourceLocation = source_location::current());
|
||||||
Database(Utils::PathString databaseFilePath,
|
Database(Utils::PathString databaseFilePath,
|
||||||
JournalMode journalMode = JournalMode::Wal,
|
JournalMode journalMode = JournalMode::Wal,
|
||||||
LockingMode lockingMode = LockingMode::Default);
|
LockingMode lockingMode = LockingMode::Default,
|
||||||
|
const source_location &sourceLocation = source_location::current());
|
||||||
Database(Utils::PathString databaseFilePath,
|
Database(Utils::PathString databaseFilePath,
|
||||||
std::chrono::milliseconds busyTimeout,
|
std::chrono::milliseconds busyTimeout,
|
||||||
JournalMode journalMode = JournalMode::Wal,
|
JournalMode journalMode = JournalMode::Wal,
|
||||||
LockingMode lockingMode = LockingMode::Default);
|
LockingMode lockingMode = LockingMode::Default,
|
||||||
|
const source_location &sourceLocation = source_location::current());
|
||||||
~Database();
|
~Database();
|
||||||
|
|
||||||
Database(const Database &) = delete;
|
Database(const Database &) = delete;
|
||||||
Database &operator=(const Database &) = delete;
|
Database &operator=(const Database &) = delete;
|
||||||
|
|
||||||
static void activateLogging();
|
static void activateLogging(const source_location &sourceLocation = source_location::current());
|
||||||
|
|
||||||
void open(LockingMode lockingMode = LockingMode::Default);
|
void open(LockingMode lockingMode = LockingMode::Default,
|
||||||
void open(Utils::PathString &&databaseFilePath, LockingMode lockingMode = LockingMode::Default);
|
const source_location &sourceLocation = source_location::current());
|
||||||
void close();
|
void open(Utils::PathString &&databaseFilePath,
|
||||||
|
LockingMode lockingMode = LockingMode::Default,
|
||||||
|
const source_location &sourceLocation = source_location::current());
|
||||||
|
void close(const source_location &sourceLocation = source_location::current());
|
||||||
|
|
||||||
bool isInitialized() const;
|
bool isInitialized() const;
|
||||||
void setIsInitialized(bool isInitialized);
|
void setIsInitialized(bool isInitialized);
|
||||||
@@ -76,34 +82,52 @@ public:
|
|||||||
void setJournalMode(JournalMode journalMode);
|
void setJournalMode(JournalMode journalMode);
|
||||||
JournalMode journalMode() const;
|
JournalMode journalMode() const;
|
||||||
|
|
||||||
LockingMode lockingMode() const;
|
LockingMode lockingMode(const source_location &sourceLocation = source_location::current()) const;
|
||||||
|
|
||||||
void setOpenMode(OpenMode openMode);
|
void setOpenMode(OpenMode openMode);
|
||||||
OpenMode openMode() const;
|
OpenMode openMode() const;
|
||||||
|
|
||||||
void execute(Utils::SmallStringView sqlStatement) override;
|
void execute(Utils::SmallStringView sqlStatement,
|
||||||
|
const source_location &sourceLocation = source_location::current()) override;
|
||||||
|
|
||||||
DatabaseBackend &backend();
|
DatabaseBackend &backend();
|
||||||
|
|
||||||
int64_t lastInsertedRowId() const
|
int64_t lastInsertedRowId(const source_location &sourceLocation = source_location::current()) const
|
||||||
{
|
{
|
||||||
return m_databaseBackend.lastInsertedRowId();
|
return m_databaseBackend.lastInsertedRowId(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLastInsertedRowId(int64_t rowId) { m_databaseBackend.setLastInsertedRowId(rowId); }
|
void setLastInsertedRowId(int64_t rowId,
|
||||||
|
const source_location &sourceLocation = source_location::current())
|
||||||
|
{
|
||||||
|
m_databaseBackend.setLastInsertedRowId(rowId, sourceLocation);
|
||||||
|
}
|
||||||
|
|
||||||
int version() const { return m_databaseBackend.version(); }
|
int version(const source_location &sourceLocation = source_location::current()) const
|
||||||
void setVersion(int version) { m_databaseBackend.setVersion(version); }
|
{
|
||||||
|
return m_databaseBackend.version(sourceLocation);
|
||||||
|
}
|
||||||
|
|
||||||
int changesCount() { return m_databaseBackend.changesCount(); }
|
void setVersion(int version, const source_location &sourceLocation = source_location::current())
|
||||||
|
{
|
||||||
|
m_databaseBackend.setVersion(version, sourceLocation);
|
||||||
|
}
|
||||||
|
|
||||||
int totalChangesCount() { return m_databaseBackend.totalChangesCount(); }
|
int changesCount(const source_location &sourceLocation = source_location::current())
|
||||||
|
{
|
||||||
|
return m_databaseBackend.changesCount(sourceLocation);
|
||||||
|
}
|
||||||
|
|
||||||
void walCheckpointFull() override
|
int totalChangesCount(const source_location &sourceLocation = source_location::current())
|
||||||
|
{
|
||||||
|
return m_databaseBackend.totalChangesCount(sourceLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void walCheckpointFull(const source_location &sourceLocation = source_location::current()) override
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock{m_databaseMutex};
|
std::lock_guard<std::mutex> lock{m_databaseMutex};
|
||||||
try {
|
try {
|
||||||
m_databaseBackend.walCheckpointFull();
|
m_databaseBackend.walCheckpointFull(sourceLocation);
|
||||||
} catch (const StatementIsBusy &) {
|
} catch (const StatementIsBusy &) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,12 +147,13 @@ public:
|
|||||||
void setAttachedTables(const Utils::SmallStringVector &tables) override;
|
void setAttachedTables(const Utils::SmallStringVector &tables) override;
|
||||||
void applyAndUpdateSessions() override;
|
void applyAndUpdateSessions() override;
|
||||||
|
|
||||||
void setBusyHandler(BusyHandler busyHandler)
|
void setBusyHandler(BusyHandler busyHandler,
|
||||||
|
const source_location &sourceLocation = source_location::current())
|
||||||
{
|
{
|
||||||
m_databaseBackend.setBusyHandler(std::move(busyHandler));
|
m_databaseBackend.setBusyHandler(std::move(busyHandler), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
SessionChangeSets changeSets() const;
|
SessionChangeSets changeSets(const source_location &sourceLocation = source_location::current()) const;
|
||||||
|
|
||||||
bool isLocked() const
|
bool isLocked() const
|
||||||
{
|
{
|
||||||
@@ -155,21 +180,21 @@ public:
|
|||||||
m_databaseMutex.unlock();
|
m_databaseMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void deferredBegin() override;
|
void deferredBegin(const source_location &sourceLocation) override;
|
||||||
void immediateBegin() override;
|
void immediateBegin(const source_location &sourceLocation) override;
|
||||||
void exclusiveBegin() override;
|
void exclusiveBegin(const source_location &sourceLocation) override;
|
||||||
void commit() override;
|
void commit(const source_location &sourceLocation) override;
|
||||||
void rollback() override;
|
void rollback(const source_location &sourceLocation) override;
|
||||||
void immediateSessionBegin() override;
|
void immediateSessionBegin(const source_location &sourceLocation) override;
|
||||||
void sessionCommit() override;
|
void sessionCommit(const source_location &sourceLocation) override;
|
||||||
void sessionRollback() override;
|
void sessionRollback(const source_location &sourceLocation) override;
|
||||||
|
|
||||||
void resetDatabaseForTestsOnly();
|
void resetDatabaseForTestsOnly(const source_location &sourceLocation = source_location::current());
|
||||||
void clearAllTablesForTestsOnly();
|
void clearAllTablesForTestsOnly(const source_location &sourceLocation = source_location::current());
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initializeTables();
|
void initializeTables();
|
||||||
void registerTransactionStatements();
|
void registerTransactionStatements(const source_location &sourceLocation);
|
||||||
void deleteTransactionStatements();
|
void deleteTransactionStatements();
|
||||||
std::mutex &databaseMutex() { return m_databaseMutex; }
|
std::mutex &databaseMutex() { return m_databaseMutex; }
|
||||||
|
|
||||||
|
@@ -26,13 +26,14 @@ namespace Sqlite {
|
|||||||
|
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
|
|
||||||
DatabaseBackend::DatabaseBackend(Database &database)
|
DatabaseBackend::DatabaseBackend(Database &database, const source_location &sourceLocation)
|
||||||
: m_database(database)
|
: m_database(database)
|
||||||
, m_databaseHandle(nullptr)
|
, m_databaseHandle(nullptr)
|
||||||
, m_busyHandler([](int) {
|
, m_busyHandler([](int) {
|
||||||
std::this_thread::sleep_for(10ms);
|
std::this_thread::sleep_for(10ms);
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
|
, m_sourceLocation{sourceLocation}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,16 +42,18 @@ DatabaseBackend::~DatabaseBackend()
|
|||||||
closeWithoutException();
|
closeWithoutException();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::setRanslatorentriesapSize(qint64 defaultSize, qint64 maximumSize)
|
void DatabaseBackend::setRanslatorentriesapSize(qint64 defaultSize,
|
||||||
|
qint64 maximumSize,
|
||||||
|
const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
int resultCode = sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, defaultSize, maximumSize);
|
int resultCode = sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, defaultSize, maximumSize);
|
||||||
checkMmapSizeIsSet(resultCode);
|
checkMmapSizeIsSet(resultCode, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::activateMultiThreading()
|
void DatabaseBackend::activateMultiThreading(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
int resultCode = sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
|
int resultCode = sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
|
||||||
checkIfMultithreadingIsActivated(resultCode);
|
checkIfMultithreadingIsActivated(resultCode, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sqliteLog(void*,int errorCode,const char *errorMessage)
|
static void sqliteLog(void*,int errorCode,const char *errorMessage)
|
||||||
@@ -58,37 +61,42 @@ static void sqliteLog(void*,int errorCode,const char *errorMessage)
|
|||||||
std::cout << "Sqlite " << sqlite3_errstr(errorCode) << ": " << errorMessage << std::endl;
|
std::cout << "Sqlite " << sqlite3_errstr(errorCode) << ": " << errorMessage << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::activateLogging()
|
void DatabaseBackend::activateLogging(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
if (qEnvironmentVariableIsSet("QTC_SQLITE_LOGGING")) {
|
if (qEnvironmentVariableIsSet("QTC_SQLITE_LOGGING")) {
|
||||||
int resultCode = sqlite3_config(SQLITE_CONFIG_LOG, sqliteLog, nullptr);
|
int resultCode = sqlite3_config(SQLITE_CONFIG_LOG, sqliteLog, nullptr);
|
||||||
checkIfLoogingIsActivated(resultCode);
|
checkIfLoogingIsActivated(resultCode, sourceLocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::initializeSqliteLibrary()
|
void DatabaseBackend::initializeSqliteLibrary(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
int resultCode = sqlite3_initialize();
|
int resultCode = sqlite3_initialize();
|
||||||
checkInitializeSqliteLibraryWasSuccesful(resultCode);
|
checkInitializeSqliteLibraryWasSuccesful(resultCode, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::shutdownSqliteLibrary()
|
void DatabaseBackend::shutdownSqliteLibrary(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
int resultCode = sqlite3_shutdown();
|
int resultCode = sqlite3_shutdown();
|
||||||
checkShutdownSqliteLibraryWasSuccesful(resultCode);
|
checkShutdownSqliteLibraryWasSuccesful(resultCode, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::checkpointFullWalLog()
|
void DatabaseBackend::checkpointFullWalLog(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
int resultCode = sqlite3_wal_checkpoint_v2(sqliteDatabaseHandle(), nullptr, SQLITE_CHECKPOINT_FULL, nullptr, nullptr);
|
int resultCode = sqlite3_wal_checkpoint_v2(sqliteDatabaseHandle(sourceLocation),
|
||||||
checkIfLogCouldBeCheckpointed(resultCode);
|
nullptr,
|
||||||
|
SQLITE_CHECKPOINT_FULL,
|
||||||
|
nullptr,
|
||||||
|
nullptr);
|
||||||
|
checkIfLogCouldBeCheckpointed(resultCode, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::open(Utils::SmallStringView databaseFilePath,
|
void DatabaseBackend::open(Utils::SmallStringView databaseFilePath,
|
||||||
OpenMode openMode,
|
OpenMode openMode,
|
||||||
JournalMode journalMode)
|
JournalMode journalMode,
|
||||||
|
const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
checkCanOpenDatabase(databaseFilePath);
|
checkCanOpenDatabase(databaseFilePath, sourceLocation);
|
||||||
|
|
||||||
sqlite3 *handle = m_databaseHandle.get();
|
sqlite3 *handle = m_databaseHandle.get();
|
||||||
int resultCode = sqlite3_open_v2(std::string(databaseFilePath).c_str(),
|
int resultCode = sqlite3_open_v2(std::string(databaseFilePath).c_str(),
|
||||||
@@ -97,42 +105,46 @@ void DatabaseBackend::open(Utils::SmallStringView databaseFilePath,
|
|||||||
nullptr);
|
nullptr);
|
||||||
m_databaseHandle.reset(handle);
|
m_databaseHandle.reset(handle);
|
||||||
|
|
||||||
checkDatabaseCouldBeOpened(resultCode);
|
checkDatabaseCouldBeOpened(resultCode, sourceLocation);
|
||||||
|
|
||||||
resultCode = sqlite3_carray_init(m_databaseHandle.get(), nullptr, nullptr);
|
resultCode = sqlite3_carray_init(m_databaseHandle.get(), nullptr, nullptr);
|
||||||
|
|
||||||
checkCarrayCannotBeIntialized(resultCode);
|
checkCarrayCannotBeIntialized(resultCode, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite3 *DatabaseBackend::sqliteDatabaseHandle() const
|
sqlite3 *DatabaseBackend::sqliteDatabaseHandle(const source_location &sourceLocation) const
|
||||||
{
|
{
|
||||||
checkDatabaseHandleIsNotNull();
|
checkDatabaseHandleIsNotNull(sourceLocation);
|
||||||
return m_databaseHandle.get();
|
return m_databaseHandle.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::setPragmaValue(Utils::SmallStringView pragmaKey, Utils::SmallStringView newPragmaValue)
|
void DatabaseBackend::setPragmaValue(Utils::SmallStringView pragmaKey,
|
||||||
|
Utils::SmallStringView newPragmaValue,
|
||||||
|
const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
ReadWriteStatement<1>{Utils::SmallString::join({"PRAGMA ", pragmaKey, "='", newPragmaValue, "'"}),
|
ReadWriteStatement<1>{Utils::SmallString::join({"PRAGMA ", pragmaKey, "='", newPragmaValue, "'"}),
|
||||||
m_database}
|
m_database}
|
||||||
.execute();
|
.execute();
|
||||||
Utils::SmallString pragmeValueInDatabase = toValue<Utils::SmallString>("PRAGMA " + pragmaKey);
|
Utils::SmallString pragmeValueInDatabase = toValue<Utils::SmallString>("PRAGMA " + pragmaKey,
|
||||||
|
sourceLocation);
|
||||||
|
|
||||||
checkPragmaValue(pragmeValueInDatabase, newPragmaValue);
|
checkPragmaValue(pragmeValueInDatabase, newPragmaValue, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::SmallString DatabaseBackend::pragmaValue(Utils::SmallStringView pragma) const
|
Utils::SmallString DatabaseBackend::pragmaValue(Utils::SmallStringView pragma,
|
||||||
|
const source_location &sourceLocation) const
|
||||||
{
|
{
|
||||||
return toValue<Utils::SmallString>("PRAGMA " + pragma);
|
return toValue<Utils::SmallString>("PRAGMA " + pragma, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::setJournalMode(JournalMode journalMode)
|
void DatabaseBackend::setJournalMode(JournalMode journalMode, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
setPragmaValue("journal_mode", journalModeToPragma(journalMode));
|
setPragmaValue("journal_mode", journalModeToPragma(journalMode), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
JournalMode DatabaseBackend::journalMode()
|
JournalMode DatabaseBackend::journalMode(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
return pragmaToJournalMode(pragmaValue("journal_mode"));
|
return pragmaToJournalMode(pragmaValue("journal_mode", sourceLocation), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -160,67 +172,69 @@ LockingMode pragmaToLockingMode(Utils::SmallStringView pragma)
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void DatabaseBackend::setLockingMode(LockingMode lockingMode)
|
void DatabaseBackend::setLockingMode(LockingMode lockingMode, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
if (lockingMode != LockingMode::Default)
|
if (lockingMode != LockingMode::Default)
|
||||||
setPragmaValue("main.locking_mode", lockingModeToPragma(lockingMode));
|
setPragmaValue("main.locking_mode", lockingModeToPragma(lockingMode), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
LockingMode DatabaseBackend::lockingMode() const
|
LockingMode DatabaseBackend::lockingMode(const source_location &sourceLocation) const
|
||||||
{
|
{
|
||||||
return pragmaToLockingMode(pragmaValue("main.locking_mode"));
|
return pragmaToLockingMode(pragmaValue("main.locking_mode", sourceLocation));
|
||||||
}
|
}
|
||||||
|
|
||||||
int DatabaseBackend::version() const
|
int DatabaseBackend::version(const source_location &sourceLocation) const
|
||||||
{
|
{
|
||||||
return toValue<int>("PRAGMA main.user_version");
|
return toValue<int>("PRAGMA main.user_version", sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::setVersion(int version)
|
void DatabaseBackend::setVersion(int version, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
ReadWriteStatement<>{Utils::SmallString{"PRAGMA main.user_version = "}
|
ReadWriteStatement<>{Utils::SmallString{"PRAGMA main.user_version = "}
|
||||||
+ Utils::SmallString::number(version),
|
+ Utils::SmallString::number(version),
|
||||||
m_database}
|
m_database,
|
||||||
.execute();
|
sourceLocation}
|
||||||
|
.execute(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
int DatabaseBackend::changesCount() const
|
int DatabaseBackend::changesCount(const source_location &sourceLocation) const
|
||||||
{
|
{
|
||||||
return sqlite3_changes(sqliteDatabaseHandle());
|
return sqlite3_changes(sqliteDatabaseHandle(sourceLocation));
|
||||||
}
|
}
|
||||||
|
|
||||||
int DatabaseBackend::totalChangesCount() const
|
int DatabaseBackend::totalChangesCount(const source_location &sourceLocation) const
|
||||||
{
|
{
|
||||||
return sqlite3_total_changes(sqliteDatabaseHandle());
|
return sqlite3_total_changes(sqliteDatabaseHandle(sourceLocation));
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t DatabaseBackend::lastInsertedRowId() const
|
int64_t DatabaseBackend::lastInsertedRowId(const source_location &sourceLocation) const
|
||||||
{
|
{
|
||||||
return sqlite3_last_insert_rowid(sqliteDatabaseHandle());
|
return sqlite3_last_insert_rowid(sqliteDatabaseHandle(sourceLocation));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::setLastInsertedRowId(int64_t rowId)
|
void DatabaseBackend::setLastInsertedRowId(int64_t rowId, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
sqlite3_set_last_insert_rowid(sqliteDatabaseHandle(), rowId);
|
sqlite3_set_last_insert_rowid(sqliteDatabaseHandle(sourceLocation), rowId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::execute(Utils::SmallStringView sqlStatement)
|
void DatabaseBackend::execute(Utils::SmallStringView sqlStatement,
|
||||||
|
const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
ReadWriteStatement<0> statement(sqlStatement, m_database);
|
ReadWriteStatement<0> statement(sqlStatement, m_database, sourceLocation);
|
||||||
statement.execute();
|
statement.execute(sourceLocation);
|
||||||
} catch (StatementIsBusy &) {
|
} catch (StatementIsBusy &) {
|
||||||
execute(sqlStatement);
|
execute(sqlStatement, sourceLocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::close()
|
void DatabaseBackend::close(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
checkForOpenDatabaseWhichCanBeClosed();
|
checkForOpenDatabaseWhichCanBeClosed(sourceLocation);
|
||||||
|
|
||||||
int resultCode = sqlite3_close(m_databaseHandle.get());
|
int resultCode = sqlite3_close(m_databaseHandle.get());
|
||||||
|
|
||||||
checkDatabaseClosing(resultCode);
|
checkDatabaseClosing(resultCode, sourceLocation);
|
||||||
|
|
||||||
m_databaseHandle.release();
|
m_databaseHandle.release();
|
||||||
}
|
}
|
||||||
@@ -246,66 +260,72 @@ int busyHandlerCallback(void *userData, int counter)
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void DatabaseBackend::registerBusyHandler()
|
void DatabaseBackend::registerBusyHandler(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
int resultCode = sqlite3_busy_handler(sqliteDatabaseHandle(),
|
int resultCode = sqlite3_busy_handler(sqliteDatabaseHandle(sourceLocation),
|
||||||
&busyHandlerCallback,
|
&busyHandlerCallback,
|
||||||
&m_busyHandler);
|
&m_busyHandler);
|
||||||
|
|
||||||
checkIfBusyTimeoutWasSet(resultCode);
|
checkIfBusyTimeoutWasSet(resultCode, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::resetDatabaseForTestsOnly()
|
void DatabaseBackend::resetDatabaseForTestsOnly(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
sqlite3_db_config(sqliteDatabaseHandle(), SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
|
sqlite3_db_config(sqliteDatabaseHandle(sourceLocation), SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
|
||||||
sqlite3_exec(sqliteDatabaseHandle(), "VACUUM", nullptr, nullptr, nullptr);
|
sqlite3_exec(sqliteDatabaseHandle(sourceLocation), "VACUUM", nullptr, nullptr, nullptr);
|
||||||
sqlite3_db_config(sqliteDatabaseHandle(), SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
|
sqlite3_db_config(sqliteDatabaseHandle(sourceLocation), SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::enableForeignKeys()
|
void DatabaseBackend::enableForeignKeys(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
sqlite3_exec(sqliteDatabaseHandle(), "PRAGMA foreign_keys=ON", nullptr, nullptr, nullptr);
|
sqlite3_exec(sqliteDatabaseHandle(sourceLocation), "PRAGMA foreign_keys=ON", nullptr, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::disableForeignKeys()
|
void DatabaseBackend::disableForeignKeys(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
sqlite3_exec(sqliteDatabaseHandle(), "PRAGMA foreign_keys=OFF", nullptr, nullptr, nullptr);
|
sqlite3_exec(sqliteDatabaseHandle(sourceLocation), "PRAGMA foreign_keys=OFF", nullptr, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::checkForOpenDatabaseWhichCanBeClosed()
|
void DatabaseBackend::checkForOpenDatabaseWhichCanBeClosed(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
if (m_databaseHandle == nullptr)
|
if (m_databaseHandle == nullptr)
|
||||||
throw DatabaseIsAlreadyClosed();
|
throw DatabaseIsAlreadyClosed(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::checkDatabaseClosing(int resultCode)
|
void DatabaseBackend::checkDatabaseClosing(int resultCode, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
switch (resultCode) {
|
switch (resultCode) {
|
||||||
case SQLITE_OK: return;
|
case SQLITE_OK: return;
|
||||||
case SQLITE_BUSY:
|
case SQLITE_BUSY:
|
||||||
throw DatabaseIsBusy();
|
throw DatabaseIsBusy(sourceLocation);
|
||||||
default:
|
default:
|
||||||
throw UnknowError("SqliteDatabaseBackend::close: unknown error happens at closing!");
|
throw UnknowError("SqliteDatabaseBackend::close: unknown error happens at closing!",
|
||||||
|
sourceLocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::checkCanOpenDatabase(Utils::SmallStringView databaseFilePath)
|
void DatabaseBackend::checkCanOpenDatabase(Utils::SmallStringView databaseFilePath,
|
||||||
|
const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
if (databaseFilePath.isEmpty())
|
if (databaseFilePath.isEmpty())
|
||||||
throw DatabaseFilePathIsEmpty("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened because the file path is empty!");
|
throw DatabaseFilePathIsEmpty("SqliteDatabaseBackend::SqliteDatabaseBackend: database "
|
||||||
|
"cannot be opened because the file path is empty!",
|
||||||
|
sourceLocation);
|
||||||
|
|
||||||
if (!QFileInfo::exists(QFileInfo(QString{databaseFilePath}).path()))
|
if (!QFileInfo::exists(QFileInfo(QString{databaseFilePath}).path()))
|
||||||
throw WrongFilePath(Utils::SmallString(databaseFilePath));
|
throw WrongFilePath(Utils::SmallString(databaseFilePath), sourceLocation);
|
||||||
|
|
||||||
if (databaseIsOpen())
|
if (databaseIsOpen())
|
||||||
throw DatabaseIsAlreadyOpen("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened because it is already open!");
|
throw DatabaseIsAlreadyOpen("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot "
|
||||||
|
"be opened because it is already open!",
|
||||||
|
sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::checkDatabaseCouldBeOpened(int resultCode)
|
void DatabaseBackend::checkDatabaseCouldBeOpened(int resultCode, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
if (resultCode != SQLITE_OK) {
|
if (resultCode != SQLITE_OK) {
|
||||||
try {
|
try {
|
||||||
Sqlite::throwError(resultCode, sqliteDatabaseHandle());
|
Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
closeWithoutException();
|
closeWithoutException();
|
||||||
throw;
|
throw;
|
||||||
@@ -313,65 +333,71 @@ void DatabaseBackend::checkDatabaseCouldBeOpened(int resultCode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::checkCarrayCannotBeIntialized(int resultCode)
|
void DatabaseBackend::checkCarrayCannotBeIntialized(int resultCode,
|
||||||
|
const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
throw DatabaseIsNotOpen();
|
throw DatabaseIsNotOpen(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::checkPragmaValue(Utils::SmallStringView databaseValue,
|
void DatabaseBackend::checkPragmaValue(Utils::SmallStringView databaseValue,
|
||||||
Utils::SmallStringView expectedValue)
|
Utils::SmallStringView expectedValue,
|
||||||
|
const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
if (databaseValue != expectedValue)
|
if (databaseValue != expectedValue)
|
||||||
throw PragmaValueNotSet();
|
throw PragmaValueNotSet(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::checkDatabaseHandleIsNotNull() const
|
void DatabaseBackend::checkDatabaseHandleIsNotNull(const source_location &sourceLocation) const
|
||||||
{
|
{
|
||||||
if (m_databaseHandle == nullptr)
|
if (m_databaseHandle == nullptr)
|
||||||
throw DatabaseIsNotOpen();
|
throw DatabaseIsNotOpen(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::checkIfMultithreadingIsActivated(int resultCode)
|
void DatabaseBackend::checkIfMultithreadingIsActivated(int resultCode,
|
||||||
|
const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
throw MultiTheadingCannotBeActivated{};
|
throw MultiTheadingCannotBeActivated{sourceLocation};
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::checkIfLoogingIsActivated(int resultCode)
|
void DatabaseBackend::checkIfLoogingIsActivated(int resultCode, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
throw LoggingCannotBeActivated{};
|
throw LoggingCannotBeActivated{sourceLocation};
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::checkMmapSizeIsSet(int resultCode)
|
void DatabaseBackend::checkMmapSizeIsSet(int resultCode, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
throw MemoryMappingCannotBeChanged{};
|
throw MemoryMappingCannotBeChanged{sourceLocation};
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::checkInitializeSqliteLibraryWasSuccesful(int resultCode)
|
void DatabaseBackend::checkInitializeSqliteLibraryWasSuccesful(int resultCode,
|
||||||
|
const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
throw LibraryCannotBeInitialized{};
|
throw LibraryCannotBeInitialized{sourceLocation};
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::checkShutdownSqliteLibraryWasSuccesful(int resultCode)
|
void DatabaseBackend::checkShutdownSqliteLibraryWasSuccesful(int resultCode,
|
||||||
|
const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
throw LibraryCannotBeShutdown{};
|
throw LibraryCannotBeShutdown{sourceLocation};
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::checkIfLogCouldBeCheckpointed(int resultCode)
|
void DatabaseBackend::checkIfLogCouldBeCheckpointed(int resultCode,
|
||||||
|
const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
throw LogCannotBeCheckpointed{};
|
throw LogCannotBeCheckpointed{sourceLocation};
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::checkIfBusyTimeoutWasSet(int resultCode)
|
void DatabaseBackend::checkIfBusyTimeoutWasSet(int resultCode, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
throw BusyTimerCannotBeSet{};
|
throw BusyTimerCannotBeSet{sourceLocation};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -398,12 +424,13 @@ Utils::SmallStringView DatabaseBackend::journalModeToPragma(JournalMode journalM
|
|||||||
return journalModeStrings[int(journalMode)];
|
return journalModeStrings[int(journalMode)];
|
||||||
}
|
}
|
||||||
|
|
||||||
JournalMode DatabaseBackend::pragmaToJournalMode(Utils::SmallStringView pragma)
|
JournalMode DatabaseBackend::pragmaToJournalMode(Utils::SmallStringView pragma,
|
||||||
|
const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
int index = indexOfPragma(pragma, journalModeStrings);
|
int index = indexOfPragma(pragma, journalModeStrings);
|
||||||
|
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
throw PragmaValueCannotBeTransformed{};
|
throw PragmaValueCannotBeTransformed{sourceLocation};
|
||||||
|
|
||||||
return static_cast<JournalMode>(index);
|
return static_cast<JournalMode>(index);
|
||||||
}
|
}
|
||||||
@@ -432,7 +459,7 @@ void DatabaseBackend::setBusyTimeout(std::chrono::milliseconds timeout)
|
|||||||
sqlite3_busy_timeout(m_databaseHandle.get(), int(timeout.count()));
|
sqlite3_busy_timeout(m_databaseHandle.get(), int(timeout.count()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::walCheckpointFull()
|
void DatabaseBackend::walCheckpointFull(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
int resultCode = sqlite3_wal_checkpoint_v2(m_databaseHandle.get(),
|
int resultCode = sqlite3_wal_checkpoint_v2(m_databaseHandle.get(),
|
||||||
nullptr,
|
nullptr,
|
||||||
@@ -441,7 +468,7 @@ void DatabaseBackend::walCheckpointFull()
|
|||||||
nullptr);
|
nullptr);
|
||||||
|
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
Sqlite::throwError(resultCode, sqliteDatabaseHandle());
|
Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::setUpdateHook(
|
void DatabaseBackend::setUpdateHook(
|
||||||
@@ -456,10 +483,11 @@ void DatabaseBackend::resetUpdateHook()
|
|||||||
sqlite3_update_hook(m_databaseHandle.get(), nullptr, nullptr);
|
sqlite3_update_hook(m_databaseHandle.get(), nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::setBusyHandler(DatabaseBackend::BusyHandler &&busyHandler)
|
void DatabaseBackend::setBusyHandler(DatabaseBackend::BusyHandler &&busyHandler,
|
||||||
|
const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
m_busyHandler = std::move(busyHandler);
|
m_busyHandler = std::move(busyHandler);
|
||||||
registerBusyHandler();
|
registerBusyHandler(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -473,36 +501,39 @@ int progressHandlerCallback(void *userData)
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void DatabaseBackend::setProgressHandler(int operationCount, ProgressHandler &&progressHandler)
|
void DatabaseBackend::setProgressHandler(int operationCount,
|
||||||
|
ProgressHandler &&progressHandler,
|
||||||
|
const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
m_progressHandler = std::move(progressHandler);
|
m_progressHandler = std::move(progressHandler);
|
||||||
|
|
||||||
if (m_progressHandler)
|
if (m_progressHandler)
|
||||||
sqlite3_progress_handler(sqliteDatabaseHandle(),
|
sqlite3_progress_handler(sqliteDatabaseHandle(sourceLocation),
|
||||||
operationCount,
|
operationCount,
|
||||||
&progressHandlerCallback,
|
&progressHandlerCallback,
|
||||||
&m_progressHandler);
|
&m_progressHandler);
|
||||||
else {
|
else {
|
||||||
sqlite3_progress_handler(sqliteDatabaseHandle(), 0, nullptr, nullptr);
|
sqlite3_progress_handler(sqliteDatabaseHandle(sourceLocation), 0, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseBackend::resetProgressHandler()
|
void DatabaseBackend::resetProgressHandler(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
sqlite3_progress_handler(sqliteDatabaseHandle(), 0, nullptr, nullptr);
|
sqlite3_progress_handler(sqliteDatabaseHandle(sourceLocation), 0, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
Type DatabaseBackend::toValue(Utils::SmallStringView sqlStatement) const
|
Type DatabaseBackend::toValue(Utils::SmallStringView sqlStatement,
|
||||||
|
const source_location &sourceLocation) const
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
ReadWriteStatement<1> statement(sqlStatement, m_database);
|
ReadWriteStatement<1> statement(sqlStatement, m_database, sourceLocation);
|
||||||
|
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
return statement.fetchValue<Type>(0);
|
return statement.fetchValue<Type>(0);
|
||||||
} catch (StatementIsBusy &) {
|
} catch (StatementIsBusy &) {
|
||||||
return toValue<Type>(sqlStatement);
|
return toValue<Type>(sqlStatement, sourceLocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "sourcelocation.h"
|
||||||
#include "sqlite3_fwd.h"
|
#include "sqlite3_fwd.h"
|
||||||
#include "sqliteglobal.h"
|
#include "sqliteglobal.h"
|
||||||
|
|
||||||
@@ -23,7 +24,7 @@ public:
|
|||||||
using BusyHandler = std::function<bool(int count)>;
|
using BusyHandler = std::function<bool(int count)>;
|
||||||
using ProgressHandler = std::function<Progress()>;
|
using ProgressHandler = std::function<Progress()>;
|
||||||
|
|
||||||
DatabaseBackend(Database &database);
|
DatabaseBackend(Database &database, const source_location &sourceLocation);
|
||||||
~DatabaseBackend();
|
~DatabaseBackend();
|
||||||
|
|
||||||
DatabaseBackend(const DatabaseBackend &) = delete;
|
DatabaseBackend(const DatabaseBackend &) = delete;
|
||||||
@@ -32,85 +33,102 @@ public:
|
|||||||
DatabaseBackend(DatabaseBackend &&) = delete;
|
DatabaseBackend(DatabaseBackend &&) = delete;
|
||||||
DatabaseBackend &operator=(DatabaseBackend &&) = delete;
|
DatabaseBackend &operator=(DatabaseBackend &&) = delete;
|
||||||
|
|
||||||
static void setRanslatorentriesapSize(qint64 defaultSize, qint64 maximumSize);
|
static void setRanslatorentriesapSize(qint64 defaultSize,
|
||||||
static void activateMultiThreading();
|
qint64 maximumSize,
|
||||||
static void activateLogging();
|
const source_location &sourceLocation);
|
||||||
static void initializeSqliteLibrary();
|
static void activateMultiThreading(const source_location &sourceLocation);
|
||||||
static void shutdownSqliteLibrary();
|
static void activateLogging(const source_location &sourceLocation);
|
||||||
void checkpointFullWalLog();
|
static void initializeSqliteLibrary(const source_location &sourceLocation);
|
||||||
|
static void shutdownSqliteLibrary(const source_location &sourceLocation);
|
||||||
|
void checkpointFullWalLog(const source_location &sourceLocation);
|
||||||
|
|
||||||
void open(Utils::SmallStringView databaseFilePath, OpenMode openMode, JournalMode journalMode);
|
void open(Utils::SmallStringView databaseFilePath,
|
||||||
void close();
|
OpenMode openMode,
|
||||||
|
JournalMode journalMode,
|
||||||
|
const source_location &sourceLocation);
|
||||||
|
void close(const source_location &sourceLocation);
|
||||||
void closeWithoutException();
|
void closeWithoutException();
|
||||||
|
|
||||||
sqlite3 *sqliteDatabaseHandle() const;
|
sqlite3 *sqliteDatabaseHandle(const source_location &sourceLocation) const;
|
||||||
|
|
||||||
void setJournalMode(JournalMode journalMode);
|
void setJournalMode(JournalMode journalMode, const source_location &sourceLocation);
|
||||||
JournalMode journalMode();
|
JournalMode journalMode(const source_location &sourceLocation);
|
||||||
|
|
||||||
void setLockingMode(LockingMode lockingMode);
|
void setLockingMode(LockingMode lockingMode, const source_location &sourceLocation);
|
||||||
LockingMode lockingMode() const;
|
LockingMode lockingMode(const source_location &sourceLocation) const;
|
||||||
|
|
||||||
Utils::SmallStringVector columnNames(Utils::SmallStringView tableName);
|
Utils::SmallStringVector columnNames(Utils::SmallStringView tableName);
|
||||||
|
|
||||||
int version() const;
|
int version(const source_location &sourceLocation) const;
|
||||||
void setVersion(int version);
|
void setVersion(int version, const source_location &sourceLocation);
|
||||||
|
|
||||||
int changesCount() const;
|
int changesCount(const source_location &sourceLocation) const;
|
||||||
int totalChangesCount() const;
|
int totalChangesCount(const source_location &sourceLocation) const;
|
||||||
|
|
||||||
int64_t lastInsertedRowId() const;
|
int64_t lastInsertedRowId(const source_location &sourceLocation) const;
|
||||||
void setLastInsertedRowId(int64_t rowId);
|
void setLastInsertedRowId(int64_t rowId, const source_location &sourceLocation);
|
||||||
|
|
||||||
void execute(Utils::SmallStringView sqlStatement);
|
void execute(Utils::SmallStringView sqlStatement, const source_location &sourceLocation);
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
Type toValue(Utils::SmallStringView sqlStatement) const;
|
Type toValue(Utils::SmallStringView sqlStatement, const source_location &sourceLocation) const;
|
||||||
|
|
||||||
static int createOpenFlags(OpenMode openMode, JournalMode journalMode);
|
static int createOpenFlags(OpenMode openMode, JournalMode journalMode);
|
||||||
|
|
||||||
void setBusyTimeout(std::chrono::milliseconds timeout);
|
void setBusyTimeout(std::chrono::milliseconds timeout);
|
||||||
|
|
||||||
void walCheckpointFull();
|
void walCheckpointFull(const source_location &sourceLocation);
|
||||||
|
|
||||||
void setUpdateHook(
|
void setUpdateHook(
|
||||||
void *object,
|
void *object,
|
||||||
void (*callback)(void *object, int, char const *database, char const *, long long rowId));
|
void (*callback)(void *object, int, char const *database, char const *, long long rowId));
|
||||||
void resetUpdateHook();
|
void resetUpdateHook();
|
||||||
|
|
||||||
void setBusyHandler(BusyHandler &&busyHandler);
|
void setBusyHandler(BusyHandler &&busyHandler, const source_location &sourceLocation);
|
||||||
void setProgressHandler(int operationCount, ProgressHandler &&progressHandler);
|
void setProgressHandler(int operationCount,
|
||||||
void resetProgressHandler();
|
ProgressHandler &&progressHandler,
|
||||||
|
const source_location &sourceLocation);
|
||||||
|
void resetProgressHandler(const source_location &sourceLocation);
|
||||||
|
|
||||||
void registerBusyHandler();
|
void registerBusyHandler(const source_location &sourceLocation);
|
||||||
|
|
||||||
void resetDatabaseForTestsOnly();
|
void resetDatabaseForTestsOnly(const source_location &sourceLocation);
|
||||||
void enableForeignKeys();
|
void enableForeignKeys(const source_location &sourceLocation);
|
||||||
void disableForeignKeys();
|
void disableForeignKeys(const source_location &sourceLocation);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool databaseIsOpen() const;
|
bool databaseIsOpen() const;
|
||||||
|
|
||||||
void setPragmaValue(Utils::SmallStringView pragma, Utils::SmallStringView value);
|
void setPragmaValue(Utils::SmallStringView pragma,
|
||||||
Utils::SmallString pragmaValue(Utils::SmallStringView pragma) const;
|
Utils::SmallStringView value,
|
||||||
|
const source_location &sourceLocation);
|
||||||
|
Utils::SmallString pragmaValue(Utils::SmallStringView pragma,
|
||||||
|
const source_location &sourceLocation) const;
|
||||||
|
|
||||||
void checkForOpenDatabaseWhichCanBeClosed();
|
void checkForOpenDatabaseWhichCanBeClosed(const source_location &sourceLocation);
|
||||||
void checkDatabaseClosing(int resultCode);
|
void checkDatabaseClosing(int resultCode, const source_location &sourceLocation);
|
||||||
void checkCanOpenDatabase(Utils::SmallStringView databaseFilePath);
|
void checkCanOpenDatabase(Utils::SmallStringView databaseFilePath,
|
||||||
void checkDatabaseCouldBeOpened(int resultCode);
|
const source_location &sourceLocation);
|
||||||
void checkCarrayCannotBeIntialized(int resultCode);
|
void checkDatabaseCouldBeOpened(int resultCode, const source_location &sourceLocation);
|
||||||
void checkPragmaValue(Utils::SmallStringView databaseValue, Utils::SmallStringView expectedValue);
|
void checkCarrayCannotBeIntialized(int resultCode, const source_location &sourceLocation);
|
||||||
void checkDatabaseHandleIsNotNull() const;
|
void checkPragmaValue(Utils::SmallStringView databaseValue,
|
||||||
static void checkIfMultithreadingIsActivated(int resultCode);
|
Utils::SmallStringView expectedValue,
|
||||||
static void checkIfLoogingIsActivated(int resultCode);
|
const source_location &sourceLocation);
|
||||||
static void checkMmapSizeIsSet(int resultCode);
|
void checkDatabaseHandleIsNotNull(const source_location &sourceLocation) const;
|
||||||
static void checkInitializeSqliteLibraryWasSuccesful(int resultCode);
|
static void checkIfMultithreadingIsActivated(int resultCode,
|
||||||
static void checkShutdownSqliteLibraryWasSuccesful(int resultCode);
|
const source_location &sourceLocation);
|
||||||
void checkIfLogCouldBeCheckpointed(int resultCode);
|
static void checkIfLoogingIsActivated(int resultCode, const source_location &sourceLocation);
|
||||||
void checkIfBusyTimeoutWasSet(int resultCode);
|
static void checkMmapSizeIsSet(int resultCode, const source_location &sourceLocation);
|
||||||
|
static void checkInitializeSqliteLibraryWasSuccesful(int resultCode,
|
||||||
|
const source_location &sourceLocation);
|
||||||
|
static void checkShutdownSqliteLibraryWasSuccesful(int resultCode,
|
||||||
|
const source_location &sourceLocation);
|
||||||
|
void checkIfLogCouldBeCheckpointed(int resultCode, const source_location &sourceLocation);
|
||||||
|
void checkIfBusyTimeoutWasSet(int resultCode, const source_location &sourceLocation);
|
||||||
|
|
||||||
static Utils::SmallStringView journalModeToPragma(JournalMode journalMode);
|
static Utils::SmallStringView journalModeToPragma(JournalMode journalMode);
|
||||||
static JournalMode pragmaToJournalMode(Utils::SmallStringView pragma);
|
static JournalMode pragmaToJournalMode(Utils::SmallStringView pragma,
|
||||||
|
const source_location &sourceLocation);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Deleter
|
struct Deleter
|
||||||
@@ -123,6 +141,7 @@ private:
|
|||||||
std::unique_ptr<sqlite3, Deleter> m_databaseHandle;
|
std::unique_ptr<sqlite3, Deleter> m_databaseHandle;
|
||||||
BusyHandler m_busyHandler;
|
BusyHandler m_busyHandler;
|
||||||
ProgressHandler m_progressHandler;
|
ProgressHandler m_progressHandler;
|
||||||
|
source_location m_sourceLocation;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Sqlite
|
} // namespace Sqlite
|
||||||
|
@@ -5,14 +5,17 @@
|
|||||||
|
|
||||||
#include <utils/smallstringvector.h>
|
#include <utils/smallstringvector.h>
|
||||||
|
|
||||||
|
#include "sourcelocation.h"
|
||||||
#include "sqliteglobal.h"
|
#include "sqliteglobal.h"
|
||||||
|
|
||||||
namespace Sqlite {
|
namespace Sqlite {
|
||||||
class DatabaseInterface
|
class DatabaseInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void walCheckpointFull() = 0;
|
virtual void walCheckpointFull(const source_location &sourceLocation = source_location::current()) = 0;
|
||||||
virtual void execute(Utils::SmallStringView sqlStatement) = 0;
|
virtual void execute(Utils::SmallStringView sqlStatement,
|
||||||
|
const source_location &sourceLocation = source_location::current())
|
||||||
|
= 0;
|
||||||
virtual void setUpdateHook(
|
virtual void setUpdateHook(
|
||||||
void *object,
|
void *object,
|
||||||
void (*)(void *object, int, char const *database, char const *, long long rowId))
|
void (*)(void *object, int, char const *database, char const *, long long rowId))
|
||||||
|
@@ -684,185 +684,185 @@ const char *CannotOpenSynbolicLink::what() const noexcept
|
|||||||
return "Sqlite::CannotOpenSynbolicLink";
|
return "Sqlite::CannotOpenSynbolicLink";
|
||||||
}
|
}
|
||||||
|
|
||||||
void throwError(int resultCode, sqlite3 *sqliteHandle)
|
void throwError(int resultCode, sqlite3 *sqliteHandle, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
switch (resultCode) {
|
switch (resultCode) {
|
||||||
case SQLITE_BUSY_RECOVERY:
|
case SQLITE_BUSY_RECOVERY:
|
||||||
throw StatementIsBusyRecovering(sqlite3_errmsg(sqliteHandle));
|
throw StatementIsBusyRecovering(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_BUSY_SNAPSHOT:
|
case SQLITE_BUSY_SNAPSHOT:
|
||||||
throw StatementIsBusySnapshot(sqlite3_errmsg(sqliteHandle));
|
throw StatementIsBusySnapshot(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_BUSY_TIMEOUT:
|
case SQLITE_BUSY_TIMEOUT:
|
||||||
throw StatementIsBusyTimeout(sqlite3_errmsg(sqliteHandle));
|
throw StatementIsBusyTimeout(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_BUSY:
|
case SQLITE_BUSY:
|
||||||
throw StatementIsBusy(sqlite3_errmsg(sqliteHandle));
|
throw StatementIsBusy(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_ERROR_MISSING_COLLSEQ:
|
case SQLITE_ERROR_MISSING_COLLSEQ:
|
||||||
throw StatementHasErrorMissingCollatingSequence(sqlite3_errmsg(sqliteHandle));
|
throw StatementHasErrorMissingCollatingSequence(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_ERROR_RETRY:
|
case SQLITE_ERROR_RETRY:
|
||||||
throw StatementHasErrorRetry(sqlite3_errmsg(sqliteHandle));
|
throw StatementHasErrorRetry(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_ERROR_SNAPSHOT:
|
case SQLITE_ERROR_SNAPSHOT:
|
||||||
throw StatementHasErrorSnapshot(sqlite3_errmsg(sqliteHandle));
|
throw StatementHasErrorSnapshot(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_ERROR:
|
case SQLITE_ERROR:
|
||||||
throw StatementHasError(sqlite3_errmsg(sqliteHandle));
|
throw StatementHasError(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_MISUSE:
|
case SQLITE_MISUSE:
|
||||||
throw StatementIsMisused(sqlite3_errmsg(sqliteHandle));
|
throw StatementIsMisused(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_CONSTRAINT_CHECK:
|
case SQLITE_CONSTRAINT_CHECK:
|
||||||
throw CheckConstraintPreventsModification(sqlite3_errmsg(sqliteHandle));
|
throw CheckConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_CONSTRAINT_COMMITHOOK:
|
case SQLITE_CONSTRAINT_COMMITHOOK:
|
||||||
throw CommitHookConstraintPreventsModification(sqlite3_errmsg(sqliteHandle));
|
throw CommitHookConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_CONSTRAINT_DATATYPE:
|
case SQLITE_CONSTRAINT_DATATYPE:
|
||||||
throw DataTypeConstraintPreventsModification(sqlite3_errmsg(sqliteHandle));
|
throw DataTypeConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_CONSTRAINT_FOREIGNKEY:
|
case SQLITE_CONSTRAINT_FOREIGNKEY:
|
||||||
throw ForeignKeyConstraintPreventsModification(sqlite3_errmsg(sqliteHandle));
|
throw ForeignKeyConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_CONSTRAINT_FUNCTION:
|
case SQLITE_CONSTRAINT_FUNCTION:
|
||||||
throw FunctionConstraintPreventsModification(sqlite3_errmsg(sqliteHandle));
|
throw FunctionConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_CONSTRAINT_NOTNULL:
|
case SQLITE_CONSTRAINT_NOTNULL:
|
||||||
throw NotNullConstraintPreventsModification(sqlite3_errmsg(sqliteHandle));
|
throw NotNullConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_CONSTRAINT_PINNED:
|
case SQLITE_CONSTRAINT_PINNED:
|
||||||
throw PinnedConstraintPreventsModification(sqlite3_errmsg(sqliteHandle));
|
throw PinnedConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_CONSTRAINT_PRIMARYKEY:
|
case SQLITE_CONSTRAINT_PRIMARYKEY:
|
||||||
throw PrimaryKeyConstraintPreventsModification(sqlite3_errmsg(sqliteHandle));
|
throw PrimaryKeyConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_CONSTRAINT_ROWID:
|
case SQLITE_CONSTRAINT_ROWID:
|
||||||
throw RowIdConstraintPreventsModification(sqlite3_errmsg(sqliteHandle));
|
throw RowIdConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_CONSTRAINT_TRIGGER:
|
case SQLITE_CONSTRAINT_TRIGGER:
|
||||||
throw TriggerConstraintPreventsModification(sqlite3_errmsg(sqliteHandle));
|
throw TriggerConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_CONSTRAINT_UNIQUE:
|
case SQLITE_CONSTRAINT_UNIQUE:
|
||||||
throw UniqueConstraintPreventsModification(sqlite3_errmsg(sqliteHandle));
|
throw UniqueConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_CONSTRAINT_VTAB:
|
case SQLITE_CONSTRAINT_VTAB:
|
||||||
throw VirtualTableConstraintPreventsModification(sqlite3_errmsg(sqliteHandle));
|
throw VirtualTableConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_CONSTRAINT:
|
case SQLITE_CONSTRAINT:
|
||||||
throw ConstraintPreventsModification(sqlite3_errmsg(sqliteHandle));
|
throw ConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_TOOBIG:
|
case SQLITE_TOOBIG:
|
||||||
throw TooBig(sqlite3_errmsg(sqliteHandle));
|
throw TooBig(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_SCHEMA:
|
case SQLITE_SCHEMA:
|
||||||
throw SchemeChangeError(sqlite3_errmsg(sqliteHandle));
|
throw SchemeChangeError(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_READONLY_CANTINIT:
|
case SQLITE_READONLY_CANTINIT:
|
||||||
throw CannotInitializeReadOnlyConnection(sqlite3_errmsg(sqliteHandle));
|
throw CannotInitializeReadOnlyConnection(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_READONLY_CANTLOCK:
|
case SQLITE_READONLY_CANTLOCK:
|
||||||
throw CannotLockReadOnlyConnection(sqlite3_errmsg(sqliteHandle));
|
throw CannotLockReadOnlyConnection(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_READONLY_DBMOVED:
|
case SQLITE_READONLY_DBMOVED:
|
||||||
throw CannotWriteToMovedDatabase(sqlite3_errmsg(sqliteHandle));
|
throw CannotWriteToMovedDatabase(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_READONLY_DIRECTORY:
|
case SQLITE_READONLY_DIRECTORY:
|
||||||
throw CannotCreateLogInReadonlyDirectory(sqlite3_errmsg(sqliteHandle));
|
throw CannotCreateLogInReadonlyDirectory(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_READONLY_RECOVERY:
|
case SQLITE_READONLY_RECOVERY:
|
||||||
throw DatabaseNeedsToBeRecovered(sqlite3_errmsg(sqliteHandle));
|
throw DatabaseNeedsToBeRecovered(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_READONLY_ROLLBACK:
|
case SQLITE_READONLY_ROLLBACK:
|
||||||
throw CannotRollbackToReadOnlyConnection(sqlite3_errmsg(sqliteHandle));
|
throw CannotRollbackToReadOnlyConnection(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_READONLY:
|
case SQLITE_READONLY:
|
||||||
throw CannotWriteToReadOnlyConnection(sqlite3_errmsg(sqliteHandle));
|
throw CannotWriteToReadOnlyConnection(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_PROTOCOL:
|
case SQLITE_PROTOCOL:
|
||||||
throw ProtocolError(sqlite3_errmsg(sqliteHandle));
|
throw ProtocolError(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_NOMEM:
|
case SQLITE_NOMEM:
|
||||||
throw std::bad_alloc();
|
throw std::bad_alloc();
|
||||||
case SQLITE_NOLFS:
|
case SQLITE_NOLFS:
|
||||||
throw DatabaseExceedsMaximumFileSize(sqlite3_errmsg(sqliteHandle));
|
throw DatabaseExceedsMaximumFileSize(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_MISMATCH:
|
case SQLITE_MISMATCH:
|
||||||
throw DataTypeMismatch(sqlite3_errmsg(sqliteHandle));
|
throw DataTypeMismatch(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_LOCKED_SHAREDCACHE:
|
case SQLITE_LOCKED_SHAREDCACHE:
|
||||||
throw ConnectionsSharedCacheIsLocked(sqlite3_errmsg(sqliteHandle));
|
throw ConnectionsSharedCacheIsLocked(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_LOCKED_VTAB:
|
case SQLITE_LOCKED_VTAB:
|
||||||
throw ConnectionsVirtualTableIsLocked(sqlite3_errmsg(sqliteHandle));
|
throw ConnectionsVirtualTableIsLocked(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_LOCKED:
|
case SQLITE_LOCKED:
|
||||||
throw ConnectionIsLocked(sqlite3_errmsg(sqliteHandle));
|
throw ConnectionIsLocked(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
case SQLITE_IOERR_READ:
|
case SQLITE_IOERR_READ:
|
||||||
throw InputOutputCannotRead();
|
throw InputOutputCannotRead(sourceLocation);
|
||||||
case SQLITE_IOERR_SHORT_READ:
|
case SQLITE_IOERR_SHORT_READ:
|
||||||
throw InputOutputCannotShortRead();
|
throw InputOutputCannotShortRead(sourceLocation);
|
||||||
case SQLITE_IOERR_WRITE:
|
case SQLITE_IOERR_WRITE:
|
||||||
throw InputOutputCannotWrite();
|
throw InputOutputCannotWrite(sourceLocation);
|
||||||
case SQLITE_IOERR_FSYNC:
|
case SQLITE_IOERR_FSYNC:
|
||||||
throw InputOutputCannotSynchronizeFile();
|
throw InputOutputCannotSynchronizeFile(sourceLocation);
|
||||||
case SQLITE_IOERR_DIR_FSYNC:
|
case SQLITE_IOERR_DIR_FSYNC:
|
||||||
throw InputOutputCannotSynchronizeDirectory();
|
throw InputOutputCannotSynchronizeDirectory(sourceLocation);
|
||||||
case SQLITE_IOERR_TRUNCATE:
|
case SQLITE_IOERR_TRUNCATE:
|
||||||
throw InputOutputCannotTruncate();
|
throw InputOutputCannotTruncate(sourceLocation);
|
||||||
case SQLITE_IOERR_FSTAT:
|
case SQLITE_IOERR_FSTAT:
|
||||||
throw InputOutputCannotFsStat();
|
throw InputOutputCannotFsStat(sourceLocation);
|
||||||
case SQLITE_IOERR_UNLOCK:
|
case SQLITE_IOERR_UNLOCK:
|
||||||
throw InputOutputCannotUnlock();
|
throw InputOutputCannotUnlock(sourceLocation);
|
||||||
case SQLITE_IOERR_RDLOCK:
|
case SQLITE_IOERR_RDLOCK:
|
||||||
throw InputOutputCannotReadLock();
|
throw InputOutputCannotReadLock(sourceLocation);
|
||||||
case SQLITE_IOERR_DELETE:
|
case SQLITE_IOERR_DELETE:
|
||||||
throw InputOutputCannotDelete();
|
throw InputOutputCannotDelete(sourceLocation);
|
||||||
case SQLITE_IOERR_BLOCKED:
|
case SQLITE_IOERR_BLOCKED:
|
||||||
throw InputOutputBlocked();
|
throw InputOutputBlocked(sourceLocation);
|
||||||
case SQLITE_IOERR_NOMEM:
|
case SQLITE_IOERR_NOMEM:
|
||||||
throw InputOutputNoMemory();
|
throw InputOutputNoMemory(sourceLocation);
|
||||||
case SQLITE_IOERR_ACCESS:
|
case SQLITE_IOERR_ACCESS:
|
||||||
throw InputOutputCannotAccess();
|
throw InputOutputCannotAccess(sourceLocation);
|
||||||
case SQLITE_IOERR_CHECKRESERVEDLOCK:
|
case SQLITE_IOERR_CHECKRESERVEDLOCK:
|
||||||
throw InputOutputCannotCheckReservedLock();
|
throw InputOutputCannotCheckReservedLock(sourceLocation);
|
||||||
case SQLITE_IOERR_LOCK:
|
case SQLITE_IOERR_LOCK:
|
||||||
throw InputOutputCannotLock();
|
throw InputOutputCannotLock(sourceLocation);
|
||||||
case SQLITE_IOERR_CLOSE:
|
case SQLITE_IOERR_CLOSE:
|
||||||
throw InputOutputCannotClose();
|
throw InputOutputCannotClose(sourceLocation);
|
||||||
case SQLITE_IOERR_DIR_CLOSE:
|
case SQLITE_IOERR_DIR_CLOSE:
|
||||||
throw InputOutputCannotCloseDirectory();
|
throw InputOutputCannotCloseDirectory(sourceLocation);
|
||||||
case SQLITE_IOERR_SHMOPEN:
|
case SQLITE_IOERR_SHMOPEN:
|
||||||
throw InputOutputCannotOpenSharedMemory();
|
throw InputOutputCannotOpenSharedMemory(sourceLocation);
|
||||||
case SQLITE_IOERR_SHMSIZE:
|
case SQLITE_IOERR_SHMSIZE:
|
||||||
throw InputOutputCannotEnlargeSharedMemory();
|
throw InputOutputCannotEnlargeSharedMemory(sourceLocation);
|
||||||
case SQLITE_IOERR_SHMLOCK:
|
case SQLITE_IOERR_SHMLOCK:
|
||||||
throw InputOutputCannotLockSharedMemory();
|
throw InputOutputCannotLockSharedMemory(sourceLocation);
|
||||||
case SQLITE_IOERR_SHMMAP:
|
case SQLITE_IOERR_SHMMAP:
|
||||||
throw InputOutputCannotMapSharedMemory();
|
throw InputOutputCannotMapSharedMemory(sourceLocation);
|
||||||
case SQLITE_IOERR_SEEK:
|
case SQLITE_IOERR_SEEK:
|
||||||
throw InputOutputCannotSeek();
|
throw InputOutputCannotSeek(sourceLocation);
|
||||||
case SQLITE_IOERR_DELETE_NOENT:
|
case SQLITE_IOERR_DELETE_NOENT:
|
||||||
throw InputOutputCannotDeleteNonExistingFile();
|
throw InputOutputCannotDeleteNonExistingFile(sourceLocation);
|
||||||
case SQLITE_IOERR_MMAP:
|
case SQLITE_IOERR_MMAP:
|
||||||
throw InputOutputCannotMemoryMap();
|
throw InputOutputCannotMemoryMap(sourceLocation);
|
||||||
case SQLITE_IOERR_GETTEMPPATH:
|
case SQLITE_IOERR_GETTEMPPATH:
|
||||||
throw InputOutputCannotGetTemporaryPath();
|
throw InputOutputCannotGetTemporaryPath(sourceLocation);
|
||||||
case SQLITE_IOERR_CONVPATH:
|
case SQLITE_IOERR_CONVPATH:
|
||||||
throw InputOutputConvPathFailed();
|
throw InputOutputConvPathFailed(sourceLocation);
|
||||||
case SQLITE_IOERR_VNODE:
|
case SQLITE_IOERR_VNODE:
|
||||||
throw InputOutputVNodeError();
|
throw InputOutputVNodeError(sourceLocation);
|
||||||
case SQLITE_IOERR_AUTH:
|
case SQLITE_IOERR_AUTH:
|
||||||
throw InputOutputCannotAuthenticate();
|
throw InputOutputCannotAuthenticate(sourceLocation);
|
||||||
case SQLITE_IOERR_BEGIN_ATOMIC:
|
case SQLITE_IOERR_BEGIN_ATOMIC:
|
||||||
throw InputOutputCannotBeginAtomic();
|
throw InputOutputCannotBeginAtomic(sourceLocation);
|
||||||
case SQLITE_IOERR_COMMIT_ATOMIC:
|
case SQLITE_IOERR_COMMIT_ATOMIC:
|
||||||
throw InputOutputCannotCommitAtomic();
|
throw InputOutputCannotCommitAtomic(sourceLocation);
|
||||||
case SQLITE_IOERR_ROLLBACK_ATOMIC:
|
case SQLITE_IOERR_ROLLBACK_ATOMIC:
|
||||||
throw InputOutputCannotRollbackAtomic();
|
throw InputOutputCannotRollbackAtomic(sourceLocation);
|
||||||
case SQLITE_IOERR_DATA:
|
case SQLITE_IOERR_DATA:
|
||||||
throw InputOutputDataError();
|
throw InputOutputDataError(sourceLocation);
|
||||||
case SQLITE_IOERR_CORRUPTFS:
|
case SQLITE_IOERR_CORRUPTFS:
|
||||||
throw InputOutputFileSystemIsCorrupt();
|
throw InputOutputFileSystemIsCorrupt(sourceLocation);
|
||||||
case SQLITE_IOERR:
|
case SQLITE_IOERR:
|
||||||
throw InputOutputError();
|
throw InputOutputError(sourceLocation);
|
||||||
case SQLITE_INTERRUPT:
|
case SQLITE_INTERRUPT:
|
||||||
throw ExecutionInterrupted();
|
throw ExecutionInterrupted(sourceLocation);
|
||||||
case SQLITE_CORRUPT_INDEX:
|
case SQLITE_CORRUPT_INDEX:
|
||||||
throw DatabaseHasCorruptIndex();
|
throw DatabaseHasCorruptIndex(sourceLocation);
|
||||||
case SQLITE_CORRUPT_SEQUENCE:
|
case SQLITE_CORRUPT_SEQUENCE:
|
||||||
throw DatabaseHasCorruptSequence();
|
throw DatabaseHasCorruptSequence(sourceLocation);
|
||||||
case SQLITE_CORRUPT_VTAB:
|
case SQLITE_CORRUPT_VTAB:
|
||||||
throw DatabaseHasCorruptVirtualTable();
|
throw DatabaseHasCorruptVirtualTable(sourceLocation);
|
||||||
case SQLITE_CORRUPT:
|
case SQLITE_CORRUPT:
|
||||||
throw DatabaseIsCorrupt();
|
throw DatabaseIsCorrupt(sourceLocation);
|
||||||
case SQLITE_CANTOPEN_CONVPATH:
|
case SQLITE_CANTOPEN_CONVPATH:
|
||||||
throw CannotOpenConvPath();
|
throw CannotOpenConvPath(sourceLocation);
|
||||||
case SQLITE_CANTOPEN_DIRTYWAL:
|
case SQLITE_CANTOPEN_DIRTYWAL:
|
||||||
throw CannotOpenDirtyWal();
|
throw CannotOpenDirtyWal(sourceLocation);
|
||||||
case SQLITE_CANTOPEN_FULLPATH:
|
case SQLITE_CANTOPEN_FULLPATH:
|
||||||
throw CannotCovertToFullPath();
|
throw CannotCovertToFullPath(sourceLocation);
|
||||||
case SQLITE_CANTOPEN_ISDIR:
|
case SQLITE_CANTOPEN_ISDIR:
|
||||||
throw CannotOpenDirectoryPath();
|
throw CannotOpenDirectoryPath(sourceLocation);
|
||||||
case SQLITE_CANTOPEN_NOTEMPDIR:
|
case SQLITE_CANTOPEN_NOTEMPDIR:
|
||||||
throw CannotOpenNoTempDir();
|
throw CannotOpenNoTempDir(sourceLocation);
|
||||||
case SQLITE_CANTOPEN_SYMLINK:
|
case SQLITE_CANTOPEN_SYMLINK:
|
||||||
throw CannotOpenSynbolicLink();
|
throw CannotOpenSynbolicLink(sourceLocation);
|
||||||
case SQLITE_CANTOPEN:
|
case SQLITE_CANTOPEN:
|
||||||
throw CannotOpen();
|
throw CannotOpen(sourceLocation);
|
||||||
case SQLITE_RANGE:
|
case SQLITE_RANGE:
|
||||||
throw BindingIndexIsOutOfRange(sqlite3_errmsg(sqliteHandle));
|
throw BindingIndexIsOutOfRange(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sqliteHandle)
|
if (sqliteHandle)
|
||||||
throw UnknowError(sqlite3_errmsg(sqliteHandle));
|
throw UnknowError(sqlite3_errmsg(sqliteHandle), sourceLocation);
|
||||||
else
|
else
|
||||||
throw UnknowError();
|
throw UnknowError({}, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Sqlite
|
} // namespace Sqlite
|
||||||
|
@@ -147,198 +147,231 @@ public:
|
|||||||
class SQLITE_EXPORT InputOutputCannotAuthenticate : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotAuthenticate : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotBeginAtomic : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotBeginAtomic : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotCommitAtomic : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotCommitAtomic : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotRollbackAtomic : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotRollbackAtomic : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputDataError : public InputOutputError
|
class SQLITE_EXPORT InputOutputDataError : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputBlocked : public InputOutputError
|
class SQLITE_EXPORT InputOutputBlocked : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputFileSystemIsCorrupt : public InputOutputError
|
class SQLITE_EXPORT InputOutputFileSystemIsCorrupt : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputVNodeError : public InputOutputError
|
class SQLITE_EXPORT InputOutputVNodeError : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputConvPathFailed : public InputOutputError
|
class SQLITE_EXPORT InputOutputConvPathFailed : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotGetTemporaryPath : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotGetTemporaryPath : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotMemoryMap : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotMemoryMap : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotDeleteNonExistingFile : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotDeleteNonExistingFile : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotSeek : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotSeek : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotMapSharedMemory : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotMapSharedMemory : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotLockSharedMemory : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotLockSharedMemory : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotEnlargeSharedMemory : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotEnlargeSharedMemory : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotOpenSharedMemory : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotOpenSharedMemory : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotCloseDirectory : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotCloseDirectory : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotClose : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotClose : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotLock : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotLock : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotCheckReservedLock : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotCheckReservedLock : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotAccess : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotAccess : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputNoMemory : public InputOutputError
|
class SQLITE_EXPORT InputOutputNoMemory : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotDelete : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotDelete : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotReadLock : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotReadLock : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotUnlock : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotUnlock : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotFsStat : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotFsStat : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotTruncate : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotTruncate : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotSynchronizeDirectory : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotSynchronizeDirectory : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotSynchronizeFile : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotSynchronizeFile : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotWrite : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotWrite : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotShortRead : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotShortRead : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQLITE_EXPORT InputOutputCannotRead : public InputOutputError
|
class SQLITE_EXPORT InputOutputCannotRead : public InputOutputError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using InputOutputError::InputOutputError;
|
||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -896,6 +929,8 @@ public:
|
|||||||
const char *what() const noexcept override;
|
const char *what() const noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[noreturn]] SQLITE_EXPORT void throwError(int resultCode, sqlite3 *sqliteHandle);
|
[[noreturn]] SQLITE_EXPORT void throwError(int resultCode,
|
||||||
|
sqlite3 *sqliteHandle,
|
||||||
|
const source_location &sourceLocation);
|
||||||
|
|
||||||
} // namespace Sqlite
|
} // namespace Sqlite
|
||||||
|
@@ -35,9 +35,9 @@ void pathExists(sqlite3_context *context, int, sqlite3_value **arguments)
|
|||||||
|
|
||||||
namespace Sqlite::FunctionRegistry {
|
namespace Sqlite::FunctionRegistry {
|
||||||
|
|
||||||
void registerPathExists(Sqlite::Database &database)
|
void registerPathExists(Sqlite::Database &database, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
sqlite3_create_function(database.backend().sqliteDatabaseHandle(),
|
sqlite3_create_function(database.backend().sqliteDatabaseHandle(sourceLocation),
|
||||||
"pathExists",
|
"pathExists",
|
||||||
1,
|
1,
|
||||||
SQLITE_UTF8 | SQLITE_INNOCUOUS,
|
SQLITE_UTF8 | SQLITE_INNOCUOUS,
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
namespace Sqlite::FunctionRegistry {
|
namespace Sqlite::FunctionRegistry {
|
||||||
|
|
||||||
SQLITE_EXPORT void registerPathExists(Sqlite::Database &database);
|
SQLITE_EXPORT void registerPathExists(
|
||||||
|
Sqlite::Database &database, const source_location &sourceLocation = source_location::current());
|
||||||
|
|
||||||
} // namespace Sqlite::FunctionRegistry
|
} // namespace Sqlite::FunctionRegistry
|
||||||
|
@@ -14,12 +14,12 @@ void LibraryInitializer::initialize()
|
|||||||
|
|
||||||
LibraryInitializer::LibraryInitializer()
|
LibraryInitializer::LibraryInitializer()
|
||||||
{
|
{
|
||||||
DatabaseBackend::initializeSqliteLibrary();
|
DatabaseBackend::initializeSqliteLibrary(source_location::current());
|
||||||
}
|
}
|
||||||
|
|
||||||
LibraryInitializer::~LibraryInitializer() noexcept(false)
|
LibraryInitializer::~LibraryInitializer() noexcept(false)
|
||||||
{
|
{
|
||||||
DatabaseBackend::shutdownSqliteLibrary();
|
DatabaseBackend::shutdownSqliteLibrary(source_location::current());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Sqlite
|
} // namespace Sqlite
|
||||||
|
@@ -11,21 +11,28 @@ class ProgressHandler
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template<typename Callable>
|
template<typename Callable>
|
||||||
ProgressHandler(Callable &&callable, int operationCount, Database &database)
|
ProgressHandler(Callable &&callable,
|
||||||
|
int operationCount,
|
||||||
|
Database &database,
|
||||||
|
const source_location &sourceLocation = source_location::current())
|
||||||
: m_database{database}
|
: m_database{database}
|
||||||
|
, m_sourceLocation{sourceLocation}
|
||||||
{
|
{
|
||||||
std::unique_lock<TransactionInterface> locker{m_database};
|
std::unique_lock<TransactionInterface> locker{m_database};
|
||||||
m_database.backend().setProgressHandler(operationCount, std::forward<Callable>(callable));
|
m_database.backend().setProgressHandler(operationCount,
|
||||||
|
std::forward<Callable>(callable),
|
||||||
|
sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
~ProgressHandler()
|
~ProgressHandler()
|
||||||
{
|
{
|
||||||
std::unique_lock<TransactionInterface> locker{m_database};
|
std::unique_lock<TransactionInterface> locker{m_database};
|
||||||
m_database.backend().resetProgressHandler();
|
m_database.backend().resetProgressHandler(m_sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Database &m_database;
|
Database &m_database;
|
||||||
|
source_location m_sourceLocation;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Sqlite
|
} // namespace Sqlite
|
||||||
|
@@ -14,12 +14,14 @@ class ReadStatement final
|
|||||||
using Base = StatementImplementation<BaseStatement, ResultCount, BindParameterCount>;
|
using Base = StatementImplementation<BaseStatement, ResultCount, BindParameterCount>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ReadStatement(Utils::SmallStringView sqlStatement, Database &database)
|
ReadStatement(Utils::SmallStringView sqlStatement,
|
||||||
: Base{sqlStatement, database}
|
Database &database,
|
||||||
|
const source_location &sourceLocation = source_location::current())
|
||||||
|
: Base{sqlStatement, database, sourceLocation}
|
||||||
{
|
{
|
||||||
checkIsReadOnlyStatement();
|
checkIsReadOnlyStatement(sourceLocation);
|
||||||
Base::checkBindingParameterCount(BindParameterCount);
|
Base::checkBindingParameterCount(BindParameterCount, sourceLocation);
|
||||||
Base::checkColumnCount(ResultCount);
|
Base::checkColumnCount(ResultCount, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
using Base::optionalValue;
|
using Base::optionalValue;
|
||||||
@@ -32,48 +34,89 @@ public:
|
|||||||
using Base::values;
|
using Base::values;
|
||||||
|
|
||||||
template<typename ResultType, typename... QueryTypes>
|
template<typename ResultType, typename... QueryTypes>
|
||||||
auto valueWithTransaction(const QueryTypes &...queryValues)
|
auto valueWithTransaction(const source_location &sourceLocation, const QueryTypes &...queryValues)
|
||||||
{
|
{
|
||||||
return withImplicitTransaction(Base::database(), [&] {
|
return withImplicitTransaction(Base::database(), [&] {
|
||||||
return Base::template value<ResultType>(queryValues...);
|
return Base::template value<ResultType>(sourceLocation, queryValues...);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ResultType, typename... QueryTypes>
|
||||||
|
auto valueWithTransaction(const QueryTypes &...queryValues)
|
||||||
|
{
|
||||||
|
static constexpr auto sourceLocation = source_location::current();
|
||||||
|
return valueWithTransaction<ResultType>(sourceLocation, queryValues...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ResultType, typename... QueryTypes>
|
||||||
|
auto optionalValueWithTransaction(const source_location &sourceLocation,
|
||||||
|
const QueryTypes &...queryValues)
|
||||||
|
{
|
||||||
|
return withImplicitTransaction(Base::database(), [&] {
|
||||||
|
return Base::template optionalValue<ResultType>(sourceLocation, queryValues...);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ResultType, typename... QueryTypes>
|
template<typename ResultType, typename... QueryTypes>
|
||||||
auto optionalValueWithTransaction(const QueryTypes &...queryValues)
|
auto optionalValueWithTransaction(const QueryTypes &...queryValues)
|
||||||
|
{
|
||||||
|
static constexpr auto sourceLocation = source_location::current();
|
||||||
|
return optionalValueWithTransaction<ResultType>(sourceLocation, queryValues...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ResultType, std::size_t capacity = 32, typename... QueryTypes>
|
||||||
|
auto valuesWithTransaction(const source_location &sourceLocation, const QueryTypes &...queryValues)
|
||||||
{
|
{
|
||||||
return withImplicitTransaction(Base::database(), [&] {
|
return withImplicitTransaction(Base::database(), [&] {
|
||||||
return Base::template optionalValue<ResultType>(queryValues...);
|
return Base::template values<ResultType, capacity>(sourceLocation, queryValues...);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ResultType, std::size_t capacity = 32, typename... QueryTypes>
|
template<typename ResultType, std::size_t capacity = 32, typename... QueryTypes>
|
||||||
auto valuesWithTransaction(const QueryTypes &...queryValues)
|
auto valuesWithTransaction(const QueryTypes &...queryValues)
|
||||||
{
|
{
|
||||||
return withImplicitTransaction(Base::database(), [&] {
|
static constexpr auto sourceLocation = source_location::current();
|
||||||
return Base::template values<ResultType, capacity>(queryValues...);
|
return valuesWithTransaction<ResultType, capacity>(sourceLocation, queryValues...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Callable, typename... QueryTypes>
|
||||||
|
void readCallbackWithTransaction(Callable &&callable,
|
||||||
|
const source_location &sourceLocation,
|
||||||
|
const QueryTypes &...queryValues)
|
||||||
|
{
|
||||||
|
withImplicitTransaction(Base::database(), [&] {
|
||||||
|
Base::readCallback(std::forward<Callable>(callable), sourceLocation, queryValues...);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Callable, typename... QueryTypes>
|
template<typename Callable, typename... QueryTypes>
|
||||||
void readCallbackWithTransaction(Callable &&callable, const QueryTypes &...queryValues)
|
void readCallbackWithTransaction(Callable &&callable, const QueryTypes &...queryValues)
|
||||||
{
|
{
|
||||||
withImplicitTransaction(Base::database(), [&] {
|
static constexpr auto sourceLocation = source_location::current();
|
||||||
Base::readCallback(std::forward<Callable>(callable), queryValues...);
|
readCallbackWithTransaction(callable, sourceLocation, queryValues...);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
template<typename Container, typename... QueryTypes>
|
||||||
|
void readToWithTransaction(Container &container,
|
||||||
|
const source_location &sourceLocation,
|
||||||
|
const QueryTypes &...queryValues)
|
||||||
|
{
|
||||||
|
withImplicitTransaction(Base::database(),
|
||||||
|
[&] { Base::readTo(container, sourceLocation, queryValues...); });
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Container, typename... QueryTypes>
|
template<typename Container, typename... QueryTypes>
|
||||||
void readToWithTransaction(Container &container, const QueryTypes &...queryValues)
|
void readToWithTransaction(Container &container, const QueryTypes &...queryValues)
|
||||||
{
|
{
|
||||||
withImplicitTransaction(Base::database(), [&] { Base::readTo(container, queryValues...); });
|
static constexpr auto sourceLocation = source_location::current();
|
||||||
|
readToWithTransaction(container, sourceLocation, queryValues...);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void checkIsReadOnlyStatement()
|
void checkIsReadOnlyStatement(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
if (!Base::isReadOnlyStatement())
|
if (!Base::isReadOnlyStatement())
|
||||||
throw NotReadOnlySqlStatement();
|
throw NotReadOnlySqlStatement(sourceLocation);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -15,11 +15,13 @@ class ReadWriteStatement final
|
|||||||
using Base = StatementImplementation<BaseStatement, ResultCount, BindParameterCount>;
|
using Base = StatementImplementation<BaseStatement, ResultCount, BindParameterCount>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ReadWriteStatement(Utils::SmallStringView sqlStatement, Database &database)
|
ReadWriteStatement(Utils::SmallStringView sqlStatement,
|
||||||
: Base{sqlStatement, database}
|
Database &database,
|
||||||
|
const source_location &sourceLocation = source_location::current())
|
||||||
|
: Base{sqlStatement, database, sourceLocation}
|
||||||
{
|
{
|
||||||
Base::checkBindingParameterCount(BindParameterCount);
|
Base::checkBindingParameterCount(BindParameterCount, sourceLocation);
|
||||||
Base::checkColumnCount(ResultCount);
|
Base::checkColumnCount(ResultCount, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
using Base::execute;
|
using Base::execute;
|
||||||
@@ -31,53 +33,98 @@ public:
|
|||||||
using Base::values;
|
using Base::values;
|
||||||
using Base::write;
|
using Base::write;
|
||||||
|
|
||||||
|
template<typename ResultType, typename... QueryTypes>
|
||||||
|
auto valueWithTransaction(const source_location &sourceLocation, const QueryTypes &...queryValues)
|
||||||
|
{
|
||||||
|
return withImmediateTransaction(
|
||||||
|
Base::database(),
|
||||||
|
[&] { return Base::template value<ResultType>(sourceLocation, queryValues...); },
|
||||||
|
sourceLocation);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename ResultType, typename... QueryTypes>
|
template<typename ResultType, typename... QueryTypes>
|
||||||
auto valueWithTransaction(const QueryTypes &...queryValues)
|
auto valueWithTransaction(const QueryTypes &...queryValues)
|
||||||
{
|
{
|
||||||
return withImmediateTransaction(Base::database(), [&] {
|
static constexpr auto sourceLocation = source_location::current();
|
||||||
return Base::template value<ResultType>(queryValues...);
|
return valueWithTransaction<ResultType>(sourceLocation, queryValues...);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
template<typename ResultType, typename... QueryTypes>
|
||||||
|
auto optionalValueWithTransaction(const source_location &sourceLocation,
|
||||||
|
const QueryTypes &...queryValues)
|
||||||
|
{
|
||||||
|
return withImmediateTransaction(
|
||||||
|
Base::database(),
|
||||||
|
[&] { return Base::template optionalValue<ResultType>(sourceLocation, queryValues...); },
|
||||||
|
sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ResultType, typename... QueryTypes>
|
template<typename ResultType, typename... QueryTypes>
|
||||||
auto optionalValueWithTransaction(const QueryTypes &...queryValues)
|
auto optionalValueWithTransaction(const QueryTypes &...queryValues)
|
||||||
{
|
{
|
||||||
return withImmediateTransaction(Base::database(), [&] {
|
static constexpr auto sourceLocation = source_location::current();
|
||||||
return Base::template optionalValue<ResultType>(queryValues...);
|
return optionalValueWithTransaction<ResultType>(sourceLocation, queryValues...);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ResultType,
|
template<typename ResultType, std::size_t capacity = 32, typename... QueryTypes>
|
||||||
std::size_t capacity = 32,
|
auto valuesWithTransaction(const source_location &sourceLocation, const QueryTypes &...queryValues)
|
||||||
typename... QueryTypes>
|
{
|
||||||
|
return withImmediateTransaction(
|
||||||
|
Base::database(),
|
||||||
|
[&] {
|
||||||
|
return Base::template values<ResultType, capacity>(sourceLocation, queryValues...);
|
||||||
|
},
|
||||||
|
sourceLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ResultType, std::size_t capacity = 32, typename... QueryTypes>
|
||||||
auto valuesWithTransaction(const QueryTypes &...queryValues)
|
auto valuesWithTransaction(const QueryTypes &...queryValues)
|
||||||
{
|
{
|
||||||
return withImmediateTransaction(Base::database(), [&] {
|
static constexpr auto sourceLocation = source_location::current();
|
||||||
return Base::template values<ResultType, capacity>(queryValues...);
|
return valuesWithTransaction<ResultType, capacity>(sourceLocation, queryValues...);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
template<typename Callable, typename... QueryTypes>
|
||||||
|
void readCallbackWithTransaction(Callable &&callable,
|
||||||
|
const source_location &sourceLocation,
|
||||||
|
const QueryTypes &...queryValues)
|
||||||
|
{
|
||||||
|
withImmediateTransaction(
|
||||||
|
Base::database(),
|
||||||
|
[&] {
|
||||||
|
Base::readCallback(std::forward<Callable>(callable), sourceLocation, queryValues...);
|
||||||
|
},
|
||||||
|
sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Callable, typename... QueryTypes>
|
template<typename Callable, typename... QueryTypes>
|
||||||
void readCallbackWithTransaction(Callable &&callable, const QueryTypes &...queryValues)
|
void readCallbackWithTransaction(Callable &&callable, const QueryTypes &...queryValues)
|
||||||
{
|
{
|
||||||
withImmediateTransaction(Base::database(), [&] {
|
static constexpr auto sourceLocation = source_location::current();
|
||||||
Base::readCallback(std::forward<Callable>(callable), queryValues...);
|
readCallbackWithTransaction(callable, sourceLocation, queryValues...);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
template<typename Container, typename... QueryTypes>
|
||||||
|
void readToWithTransaction(Container &container,
|
||||||
|
const source_location &sourceLocation,
|
||||||
|
const QueryTypes &...queryValues)
|
||||||
|
{
|
||||||
|
withImmediateTransaction(
|
||||||
|
Base::database(),
|
||||||
|
[&] { Base::readTo(container, sourceLocation, queryValues...); },
|
||||||
|
sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Container, typename... QueryTypes>
|
template<typename Container, typename... QueryTypes>
|
||||||
void readToWithTransaction(Container &container, const QueryTypes &...queryValues)
|
void readToWithTransaction(Container &container, const QueryTypes &...queryValues)
|
||||||
{
|
{
|
||||||
withImmediateTransaction(Base::database(), [&] {
|
static constexpr auto sourceLocation = source_location::current();
|
||||||
Base::readTo(container, queryValues...);
|
readToWithTransaction(container, sourceLocation, queryValues...);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void executeWithTransaction()
|
void executeWithTransaction(const source_location &sourceLocation = source_location::current())
|
||||||
{
|
{
|
||||||
withImmediateTransaction(Base::database(), [&] {
|
withImmediateTransaction(Base::database(), [&] { Base::execute(sourceLocation); }, sourceLocation);
|
||||||
Base::execute();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -14,19 +14,19 @@ namespace Sqlite {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void checkResultCode(int resultCode)
|
void checkResultCode(int resultCode, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
switch (resultCode) {
|
switch (resultCode) {
|
||||||
case SQLITE_NOMEM:
|
case SQLITE_NOMEM:
|
||||||
throw std::bad_alloc();
|
throw std::bad_alloc();
|
||||||
case SQLITE_SCHEMA:
|
case SQLITE_SCHEMA:
|
||||||
throw CannotApplyChangeSet();
|
throw CannotApplyChangeSet(sourceLocation);
|
||||||
case SQLITE_MISUSE:
|
case SQLITE_MISUSE:
|
||||||
throw ChangeSetIsMisused();
|
throw ChangeSetIsMisused(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
throw UnknowError();
|
throw UnknowError({}, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
int xConflict(void *, int conflict, sqlite3_changeset_iter *)
|
int xConflict(void *, int conflict, sqlite3_changeset_iter *)
|
||||||
@@ -48,11 +48,12 @@ int xConflict(void *, int conflict, sqlite3_changeset_iter *)
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void Sessions::attachTables(const Utils::SmallStringVector &tableNames)
|
void Sessions::attachTables(const Utils::SmallStringVector &tableNames,
|
||||||
|
const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
for (Utils::SmallStringView tableName : tableNames) {
|
for (Utils::SmallStringView tableName : tableNames) {
|
||||||
int resultCode = sqlite3session_attach(session.get(), std::string(tableName).c_str());
|
int resultCode = sqlite3session_attach(session.get(), std::string(tableName).c_str());
|
||||||
checkResultCode(resultCode);
|
checkResultCode(resultCode, sourceLocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,25 +64,25 @@ void Sessions::setAttachedTables(Utils::SmallStringVector tables)
|
|||||||
tableNames = std::move(tables);
|
tableNames = std::move(tables);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sessions::create()
|
void Sessions::create(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
sqlite3_session *newSession = nullptr;
|
sqlite3_session *newSession = nullptr;
|
||||||
int resultCode = sqlite3session_create(database.backend().sqliteDatabaseHandle(),
|
int resultCode = sqlite3session_create(database.backend().sqliteDatabaseHandle(sourceLocation),
|
||||||
std::string(databaseName).c_str(),
|
std::string(databaseName).c_str(),
|
||||||
&newSession);
|
&newSession);
|
||||||
session.reset(newSession);
|
session.reset(newSession);
|
||||||
|
|
||||||
checkResultCode(resultCode);
|
checkResultCode(resultCode, sourceLocation);
|
||||||
|
|
||||||
attachTables(tableNames);
|
attachTables(tableNames, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sessions::commit()
|
void Sessions::commit(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
if (session && !sqlite3session_isempty(session.get())) {
|
if (session && !sqlite3session_isempty(session.get())) {
|
||||||
SessionChangeSet changeSet{*this};
|
SessionChangeSet changeSet{*this};
|
||||||
|
|
||||||
insertSession.write(changeSet.asBlobView());
|
insertSession.write(sourceLocation, changeSet.asBlobView());
|
||||||
}
|
}
|
||||||
|
|
||||||
session.reset();
|
session.reset();
|
||||||
@@ -92,7 +93,8 @@ void Sessions::rollback()
|
|||||||
session.reset();
|
session.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Internal::SessionsBase::createSessionTable(Database &database)
|
void Internal::SessionsBase::createSessionTable(Database &database,
|
||||||
|
const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
Sqlite::Table table;
|
Sqlite::Table table;
|
||||||
table.setUseIfNotExists(true);
|
table.setUseIfNotExists(true);
|
||||||
@@ -100,20 +102,22 @@ void Internal::SessionsBase::createSessionTable(Database &database)
|
|||||||
table.addColumn("id", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{AutoIncrement::Yes}});
|
table.addColumn("id", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{AutoIncrement::Yes}});
|
||||||
table.addColumn("changeset", Sqlite::ColumnType::Blob);
|
table.addColumn("changeset", Sqlite::ColumnType::Blob);
|
||||||
|
|
||||||
table.initialize(database);
|
table.initialize(database, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sessions::revert()
|
void Sessions::revert(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
ReadStatement<1> selectChangeSets{Utils::PathString::join({"SELECT changeset FROM ",
|
ReadStatement<1> selectChangeSets{Utils::PathString::join({"SELECT changeset FROM ",
|
||||||
sessionsTableName,
|
sessionsTableName,
|
||||||
" ORDER BY id DESC"}),
|
" ORDER BY id DESC"}),
|
||||||
database};
|
database,
|
||||||
|
sourceLocation};
|
||||||
|
|
||||||
auto changeSets = selectChangeSets.values<SessionChangeSet, 1024>();
|
auto changeSets = selectChangeSets.values<SessionChangeSet, 1024>(sourceLocation);
|
||||||
|
|
||||||
for (auto &changeSet : changeSets) {
|
for (auto &changeSet : changeSets) {
|
||||||
int resultCode = sqlite3changeset_apply_v2(database.backend().sqliteDatabaseHandle(),
|
int resultCode = sqlite3changeset_apply_v2(database.backend().sqliteDatabaseHandle(
|
||||||
|
sourceLocation),
|
||||||
changeSet.size(),
|
changeSet.size(),
|
||||||
changeSet.data(),
|
changeSet.data(),
|
||||||
nullptr,
|
nullptr,
|
||||||
@@ -123,21 +127,23 @@ void Sessions::revert()
|
|||||||
nullptr,
|
nullptr,
|
||||||
SQLITE_CHANGESETAPPLY_INVERT
|
SQLITE_CHANGESETAPPLY_INVERT
|
||||||
| SQLITE_CHANGESETAPPLY_NOSAVEPOINT);
|
| SQLITE_CHANGESETAPPLY_NOSAVEPOINT);
|
||||||
checkResultCode(resultCode);
|
checkResultCode(resultCode, sourceLocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sessions::apply()
|
void Sessions::apply(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
ReadStatement<1> selectChangeSets{Utils::PathString::join({"SELECT changeset FROM ",
|
ReadStatement<1> selectChangeSets{Utils::PathString::join({"SELECT changeset FROM ",
|
||||||
sessionsTableName,
|
sessionsTableName,
|
||||||
" ORDER BY id"}),
|
" ORDER BY id"}),
|
||||||
database};
|
database,
|
||||||
|
sourceLocation};
|
||||||
|
|
||||||
auto changeSets = selectChangeSets.values<SessionChangeSet, 1024>();
|
auto changeSets = selectChangeSets.values<SessionChangeSet, 1024>(sourceLocation);
|
||||||
|
|
||||||
for (auto &changeSet : changeSets) {
|
for (auto &changeSet : changeSets) {
|
||||||
int resultCode = sqlite3changeset_apply_v2(database.backend().sqliteDatabaseHandle(),
|
int resultCode = sqlite3changeset_apply_v2(database.backend().sqliteDatabaseHandle(
|
||||||
|
sourceLocation),
|
||||||
changeSet.size(),
|
changeSet.size(),
|
||||||
changeSet.data(),
|
changeSet.data(),
|
||||||
nullptr,
|
nullptr,
|
||||||
@@ -146,31 +152,35 @@ void Sessions::apply()
|
|||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
SQLITE_CHANGESETAPPLY_NOSAVEPOINT);
|
SQLITE_CHANGESETAPPLY_NOSAVEPOINT);
|
||||||
checkResultCode(resultCode);
|
checkResultCode(resultCode, sourceLocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sessions::applyAndUpdateSessions()
|
void Sessions::applyAndUpdateSessions(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
create();
|
create(sourceLocation);
|
||||||
apply();
|
apply(sourceLocation);
|
||||||
deleteAll();
|
deleteAll(sourceLocation);
|
||||||
commit();
|
commit(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sessions::deleteAll()
|
void Sessions::deleteAll(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
WriteStatement<0>{Utils::SmallString::join({"DELETE FROM ", sessionsTableName}), database}.execute();
|
WriteStatement<0>{Utils::SmallString::join({"DELETE FROM ", sessionsTableName}),
|
||||||
|
database,
|
||||||
|
sourceLocation}
|
||||||
|
.execute(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
SessionChangeSets Sessions::changeSets() const
|
SessionChangeSets Sessions::changeSets(const source_location &sourceLocation) const
|
||||||
{
|
{
|
||||||
ReadStatement<1> selectChangeSets{Utils::PathString::join({"SELECT changeset FROM ",
|
ReadStatement<1> selectChangeSets{Utils::PathString::join({"SELECT changeset FROM ",
|
||||||
sessionsTableName,
|
sessionsTableName,
|
||||||
" ORDER BY id DESC"}),
|
" ORDER BY id DESC"}),
|
||||||
database};
|
database,
|
||||||
|
sourceLocation};
|
||||||
|
|
||||||
return selectChangeSets.values<SessionChangeSet, 1024>();
|
return selectChangeSets.values<SessionChangeSet, 1024>(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sessions::Deleter::operator()(sqlite3_session *session)
|
void Sessions::Deleter::operator()(sqlite3_session *session)
|
||||||
|
@@ -15,13 +15,15 @@ namespace Internal {
|
|||||||
class SQLITE_EXPORT SessionsBase
|
class SQLITE_EXPORT SessionsBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SessionsBase(Database &database, Utils::SmallStringView sessionsTableName)
|
SessionsBase(Database &database,
|
||||||
|
Utils::SmallStringView sessionsTableName,
|
||||||
|
const source_location &sourceLocation)
|
||||||
: sessionsTableName(sessionsTableName)
|
: sessionsTableName(sessionsTableName)
|
||||||
{
|
{
|
||||||
createSessionTable(database);
|
createSessionTable(database, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createSessionTable(Database &database);
|
void createSessionTable(Database &database, const source_location &sourceLocation);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Utils::SmallString sessionsTableName;
|
Utils::SmallString sessionsTableName;
|
||||||
@@ -33,31 +35,33 @@ class SQLITE_EXPORT Sessions : public Internal::SessionsBase
|
|||||||
public:
|
public:
|
||||||
Sessions(Database &database,
|
Sessions(Database &database,
|
||||||
Utils::SmallStringView databaseName,
|
Utils::SmallStringView databaseName,
|
||||||
Utils::SmallStringView sessionsTableName)
|
Utils::SmallStringView sessionsTableName,
|
||||||
: SessionsBase(database, sessionsTableName)
|
const source_location &sourceLocation = source_location::current())
|
||||||
|
: SessionsBase(database, sessionsTableName, sourceLocation)
|
||||||
, database(database)
|
, database(database)
|
||||||
, insertSession{Utils::PathString::join(
|
, insertSession{Utils::PathString::join(
|
||||||
{"INSERT INTO ", sessionsTableName, "(changeset) VALUES(?)"}),
|
{"INSERT INTO ", sessionsTableName, "(changeset) VALUES(?)"}),
|
||||||
database}
|
database,
|
||||||
|
sourceLocation}
|
||||||
, databaseName(databaseName)
|
, databaseName(databaseName)
|
||||||
{}
|
{}
|
||||||
~Sessions();
|
~Sessions();
|
||||||
|
|
||||||
void setAttachedTables(Utils::SmallStringVector tables);
|
void setAttachedTables(Utils::SmallStringVector tables);
|
||||||
|
|
||||||
void create();
|
void create(const source_location &sourceLocation = source_location::current());
|
||||||
void commit();
|
void commit(const source_location &sourceLocation = source_location::current());
|
||||||
void rollback();
|
void rollback();
|
||||||
|
|
||||||
void revert();
|
void revert(const source_location &sourceLocation = source_location::current());
|
||||||
void apply();
|
void apply(const source_location &sourceLocation = source_location::current());
|
||||||
void applyAndUpdateSessions();
|
void applyAndUpdateSessions(const source_location &sourceLocation = source_location::current());
|
||||||
void deleteAll();
|
void deleteAll(const source_location &sourceLocation = source_location::current());
|
||||||
|
|
||||||
SessionChangeSets changeSets() const;
|
SessionChangeSets changeSets(const source_location &sourceLocation = source_location::current()) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void attachTables(const Utils::SmallStringVector &tables);
|
void attachTables(const Utils::SmallStringVector &tables, const source_location &sourceLocation);
|
||||||
|
|
||||||
struct Deleter
|
struct Deleter
|
||||||
{
|
{
|
||||||
|
@@ -136,8 +136,9 @@ public:
|
|||||||
return m_isReady;
|
return m_isReady;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Database>
|
template<typename Database>
|
||||||
void initialize(Database &database)
|
void initialize(Database &database,
|
||||||
|
const source_location &sourceLocation = source_location::current())
|
||||||
{
|
{
|
||||||
CreateTableSqlStatementBuilder<ColumnType> builder;
|
CreateTableSqlStatementBuilder<ColumnType> builder;
|
||||||
|
|
||||||
@@ -148,17 +149,18 @@ public:
|
|||||||
builder.setColumns(m_sqliteColumns);
|
builder.setColumns(m_sqliteColumns);
|
||||||
builder.setConstraints(m_tableConstraints);
|
builder.setConstraints(m_tableConstraints);
|
||||||
|
|
||||||
database.execute(builder.sqlStatement());
|
database.execute(builder.sqlStatement(), sourceLocation);
|
||||||
|
|
||||||
initializeIndices(database);
|
initializeIndices(database, sourceLocation);
|
||||||
|
|
||||||
m_isReady = true;
|
m_isReady = true;
|
||||||
}
|
}
|
||||||
template <typename Database>
|
|
||||||
void initializeIndices(Database &database)
|
template<typename Database>
|
||||||
|
void initializeIndices(Database &database, const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
for (const Index &index : m_sqliteIndices)
|
for (const Index &index : m_sqliteIndices)
|
||||||
database.execute(index.sqlStatement());
|
database.execute(index.sqlStatement(), sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator==(const BasicTable &first, const BasicTable &second)
|
friend bool operator==(const BasicTable &first, const BasicTable &second)
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "sourcelocation.h"
|
||||||
#include "sqliteglobal.h"
|
#include "sqliteglobal.h"
|
||||||
|
|
||||||
#include <utils/smallstringview.h>
|
#include <utils/smallstringview.h>
|
||||||
@@ -22,16 +23,16 @@ public:
|
|||||||
TransactionInterface(const TransactionInterface &) = delete;
|
TransactionInterface(const TransactionInterface &) = delete;
|
||||||
TransactionInterface &operator=(const TransactionInterface &) = delete;
|
TransactionInterface &operator=(const TransactionInterface &) = delete;
|
||||||
|
|
||||||
virtual void deferredBegin() = 0;
|
virtual void deferredBegin(const source_location &sourceLocation) = 0;
|
||||||
virtual void immediateBegin() = 0;
|
virtual void immediateBegin(const source_location &sourceLocation) = 0;
|
||||||
virtual void exclusiveBegin() = 0;
|
virtual void exclusiveBegin(const source_location &sourceLocation) = 0;
|
||||||
virtual void commit() = 0;
|
virtual void commit(const source_location &sourceLocation) = 0;
|
||||||
virtual void rollback() = 0;
|
virtual void rollback(const source_location &sourceLocation) = 0;
|
||||||
virtual void lock() = 0;
|
virtual void lock() = 0;
|
||||||
virtual void unlock() = 0;
|
virtual void unlock() = 0;
|
||||||
virtual void immediateSessionBegin() = 0;
|
virtual void immediateSessionBegin(const source_location &sourceLocation) = 0;
|
||||||
virtual void sessionCommit() = 0;
|
virtual void sessionCommit(const source_location &sourceLocation) = 0;
|
||||||
virtual void sessionRollback() = 0;
|
virtual void sessionRollback(const source_location &sourceLocation) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~TransactionInterface() = default;
|
~TransactionInterface() = default;
|
||||||
@@ -46,15 +47,16 @@ public:
|
|||||||
AbstractTransaction(const AbstractTransaction &) = delete;
|
AbstractTransaction(const AbstractTransaction &) = delete;
|
||||||
AbstractTransaction &operator=(const AbstractTransaction &) = delete;
|
AbstractTransaction &operator=(const AbstractTransaction &) = delete;
|
||||||
|
|
||||||
void commit()
|
void commit(const source_location &sourceLocation = source_location::current())
|
||||||
{
|
{
|
||||||
m_interface.commit();
|
m_interface.commit(sourceLocation);
|
||||||
m_isAlreadyCommited = true;
|
m_isAlreadyCommited = true;
|
||||||
m_locker.unlock();
|
m_locker.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~AbstractTransaction() = default;
|
~AbstractTransaction() = default;
|
||||||
|
|
||||||
AbstractTransaction(TransactionInterface &transactionInterface)
|
AbstractTransaction(TransactionInterface &transactionInterface)
|
||||||
: m_interface(transactionInterface)
|
: m_interface(transactionInterface)
|
||||||
{
|
{
|
||||||
@@ -94,9 +96,9 @@ public:
|
|||||||
AbstractThrowingSessionTransaction(const AbstractThrowingSessionTransaction &) = delete;
|
AbstractThrowingSessionTransaction(const AbstractThrowingSessionTransaction &) = delete;
|
||||||
AbstractThrowingSessionTransaction &operator=(const AbstractThrowingSessionTransaction &) = delete;
|
AbstractThrowingSessionTransaction &operator=(const AbstractThrowingSessionTransaction &) = delete;
|
||||||
|
|
||||||
void commit()
|
void commit(const source_location &sourceLocation = source_location::current())
|
||||||
{
|
{
|
||||||
m_interface.sessionCommit();
|
m_interface.sessionCommit(sourceLocation);
|
||||||
m_isAlreadyCommited = true;
|
m_isAlreadyCommited = true;
|
||||||
m_locker.unlock();
|
m_locker.unlock();
|
||||||
}
|
}
|
||||||
@@ -105,7 +107,7 @@ public:
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if (m_rollback)
|
if (m_rollback)
|
||||||
m_interface.sessionRollback();
|
m_interface.sessionRollback(m_sourceLocation);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
if (!std::uncaught_exceptions())
|
if (!std::uncaught_exceptions())
|
||||||
throw;
|
throw;
|
||||||
@@ -113,11 +115,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
AbstractThrowingSessionTransaction(TransactionInterface &transactionInterface)
|
AbstractThrowingSessionTransaction(TransactionInterface &transactionInterface,
|
||||||
: m_interface(transactionInterface)
|
const source_location &sourceLocation)
|
||||||
|
: m_sourceLocation(sourceLocation)
|
||||||
|
, m_interface(transactionInterface)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
source_location m_sourceLocation;
|
||||||
TransactionInterface &m_interface;
|
TransactionInterface &m_interface;
|
||||||
std::unique_lock<TransactionInterface> m_locker{m_interface};
|
std::unique_lock<TransactionInterface> m_locker{m_interface};
|
||||||
bool m_isAlreadyCommited = false;
|
bool m_isAlreadyCommited = false;
|
||||||
@@ -136,7 +141,7 @@ public:
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if (Base::m_rollback)
|
if (Base::m_rollback)
|
||||||
Base::m_interface.rollback();
|
Base::m_interface.rollback(m_sourceLocation);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
if (!std::uncaught_exceptions())
|
if (!std::uncaught_exceptions())
|
||||||
throw;
|
throw;
|
||||||
@@ -144,10 +149,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
AbstractThrowingTransaction(TransactionInterface &transactionInterface)
|
AbstractThrowingTransaction(TransactionInterface &transactionInterface,
|
||||||
|
const source_location &sourceLocation)
|
||||||
: AbstractTransaction<TransactionInterface>(transactionInterface)
|
: AbstractTransaction<TransactionInterface>(transactionInterface)
|
||||||
|
, m_sourceLocation(sourceLocation)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
source_location m_sourceLocation;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename TransactionInterface>
|
template<typename TransactionInterface>
|
||||||
@@ -162,26 +172,33 @@ public:
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if (Base::m_rollback)
|
if (Base::m_rollback)
|
||||||
Base::m_interface.rollback();
|
Base::m_interface.rollback(m_sourceLocation);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
AbstractNonThrowingDestructorTransaction(TransactionInterface &transactionInterface)
|
AbstractNonThrowingDestructorTransaction(TransactionInterface &transactionInterface,
|
||||||
|
const source_location &sourceLocation)
|
||||||
: AbstractTransaction<TransactionInterface>(transactionInterface)
|
: AbstractTransaction<TransactionInterface>(transactionInterface)
|
||||||
|
, m_sourceLocation(sourceLocation)
|
||||||
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
source_location m_sourceLocation;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename BaseTransaction>
|
template<typename BaseTransaction>
|
||||||
class BasicDeferredTransaction : public BaseTransaction
|
class BasicDeferredTransaction : public BaseTransaction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BasicDeferredTransaction(typename BaseTransaction::Transaction &transactionInterface)
|
BasicDeferredTransaction(typename BaseTransaction::Transaction &transactionInterface,
|
||||||
: BaseTransaction(transactionInterface)
|
const source_location &sourceLocation = source_location::current())
|
||||||
|
: BaseTransaction(transactionInterface, sourceLocation)
|
||||||
{
|
{
|
||||||
transactionInterface.deferredBegin();
|
transactionInterface.deferredBegin(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
~BasicDeferredTransaction()
|
~BasicDeferredTransaction()
|
||||||
@@ -201,19 +218,20 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename Transaction, typename TransactionInterface, typename Callable>
|
template<typename Transaction, typename TransactionInterface, typename Callable>
|
||||||
auto withTransaction(TransactionInterface &transactionInterface, Callable &&callable)
|
auto withTransaction(TransactionInterface &transactionInterface,
|
||||||
-> std::invoke_result_t<Callable>
|
Callable &&callable,
|
||||||
|
const source_location &sourceLocation) -> std::invoke_result_t<Callable>
|
||||||
{
|
{
|
||||||
Transaction transaction{transactionInterface};
|
Transaction transaction{transactionInterface, sourceLocation};
|
||||||
|
|
||||||
if constexpr (std::is_void_v<std::invoke_result_t<Callable>>) {
|
if constexpr (std::is_void_v<std::invoke_result_t<Callable>>) {
|
||||||
callable();
|
callable();
|
||||||
|
|
||||||
transaction.commit();
|
transaction.commit(sourceLocation);
|
||||||
} else {
|
} else {
|
||||||
auto results = callable();
|
auto results = callable();
|
||||||
|
|
||||||
transaction.commit();
|
transaction.commit(sourceLocation);
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
@@ -232,18 +250,25 @@ auto withImplicitTransaction(TransactionInterface &transactionInterface, Callabl
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename TransactionInterface, typename Callable>
|
template<typename TransactionInterface, typename Callable>
|
||||||
auto withDeferredTransaction(TransactionInterface &transactionInterface, Callable &&callable)
|
auto withDeferredTransaction(TransactionInterface &transactionInterface,
|
||||||
|
Callable &&callable,
|
||||||
|
const source_location &sourceLocation = source_location::current())
|
||||||
{
|
{
|
||||||
if constexpr (std::is_void_v<std::invoke_result_t<Callable>>) {
|
if constexpr (std::is_void_v<std::invoke_result_t<Callable>>) {
|
||||||
withTransaction<DeferredTransaction<TransactionInterface>>(transactionInterface,
|
withTransaction<DeferredTransaction<TransactionInterface>>(transactionInterface,
|
||||||
std::forward<Callable>(callable));
|
std::forward<Callable>(callable),
|
||||||
|
sourceLocation);
|
||||||
} else {
|
} else {
|
||||||
return withTransaction<DeferredTransaction<TransactionInterface>>(transactionInterface,
|
return withTransaction<DeferredTransaction<TransactionInterface>>(transactionInterface,
|
||||||
std::forward<Callable>(
|
std::forward<Callable>(
|
||||||
callable));
|
callable),
|
||||||
|
sourceLocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename TransactionInterface>
|
||||||
|
DeferredTransaction(TransactionInterface &, const source_location &)
|
||||||
|
-> DeferredTransaction<TransactionInterface>;
|
||||||
template<typename TransactionInterface>
|
template<typename TransactionInterface>
|
||||||
DeferredTransaction(TransactionInterface &) -> DeferredTransaction<TransactionInterface>;
|
DeferredTransaction(TransactionInterface &) -> DeferredTransaction<TransactionInterface>;
|
||||||
|
|
||||||
@@ -257,6 +282,9 @@ public:
|
|||||||
using Base::Base;
|
using Base::Base;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename TransactionInterface>
|
||||||
|
DeferredNonThrowingDestructorTransaction(TransactionInterface &, const source_location &)
|
||||||
|
-> DeferredNonThrowingDestructorTransaction<TransactionInterface>;
|
||||||
template<typename TransactionInterface>
|
template<typename TransactionInterface>
|
||||||
DeferredNonThrowingDestructorTransaction(TransactionInterface &)
|
DeferredNonThrowingDestructorTransaction(TransactionInterface &)
|
||||||
-> DeferredNonThrowingDestructorTransaction<TransactionInterface>;
|
-> DeferredNonThrowingDestructorTransaction<TransactionInterface>;
|
||||||
@@ -265,10 +293,11 @@ template<typename BaseTransaction>
|
|||||||
class BasicImmediateTransaction : public BaseTransaction
|
class BasicImmediateTransaction : public BaseTransaction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BasicImmediateTransaction(typename BaseTransaction::Transaction &transactionInterface)
|
BasicImmediateTransaction(typename BaseTransaction::Transaction &transactionInterface,
|
||||||
: BaseTransaction(transactionInterface)
|
const source_location &sourceLocation = source_location::current())
|
||||||
|
: BaseTransaction(transactionInterface, sourceLocation)
|
||||||
{
|
{
|
||||||
transactionInterface.immediateBegin();
|
transactionInterface.immediateBegin(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
~BasicImmediateTransaction()
|
~BasicImmediateTransaction()
|
||||||
@@ -288,19 +317,25 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename TransactionInterface, typename Callable>
|
template<typename TransactionInterface, typename Callable>
|
||||||
auto withImmediateTransaction(TransactionInterface &transactionInterface, Callable &&callable)
|
auto withImmediateTransaction(TransactionInterface &transactionInterface,
|
||||||
|
Callable &&callable,
|
||||||
|
const source_location &sourceLocation = source_location::current())
|
||||||
{
|
{
|
||||||
if constexpr (std::is_void_v<std::invoke_result_t<Callable>>) {
|
if constexpr (std::is_void_v<std::invoke_result_t<Callable>>) {
|
||||||
withTransaction<ImmediateTransaction<TransactionInterface>>(transactionInterface,
|
withTransaction<ImmediateTransaction<TransactionInterface>>(transactionInterface,
|
||||||
std::forward<Callable>(
|
std::forward<Callable>(callable),
|
||||||
callable));
|
sourceLocation);
|
||||||
} else {
|
} else {
|
||||||
return withTransaction<ImmediateTransaction<TransactionInterface>>(transactionInterface,
|
return withTransaction<ImmediateTransaction<TransactionInterface>>(transactionInterface,
|
||||||
std::forward<Callable>(
|
std::forward<Callable>(
|
||||||
callable));
|
callable),
|
||||||
|
sourceLocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename TransactionInterface>
|
||||||
|
ImmediateTransaction(TransactionInterface &, const source_location &)
|
||||||
|
-> ImmediateTransaction<TransactionInterface>;
|
||||||
template<typename TransactionInterface>
|
template<typename TransactionInterface>
|
||||||
ImmediateTransaction(TransactionInterface &) -> ImmediateTransaction<TransactionInterface>;
|
ImmediateTransaction(TransactionInterface &) -> ImmediateTransaction<TransactionInterface>;
|
||||||
|
|
||||||
@@ -314,6 +349,9 @@ public:
|
|||||||
using Base::Base;
|
using Base::Base;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename TransactionInterface>
|
||||||
|
ImmediateNonThrowingDestructorTransaction(TransactionInterface &, const source_location &)
|
||||||
|
-> ImmediateNonThrowingDestructorTransaction<TransactionInterface>;
|
||||||
template<typename TransactionInterface>
|
template<typename TransactionInterface>
|
||||||
ImmediateNonThrowingDestructorTransaction(TransactionInterface &)
|
ImmediateNonThrowingDestructorTransaction(TransactionInterface &)
|
||||||
-> ImmediateNonThrowingDestructorTransaction<TransactionInterface>;
|
-> ImmediateNonThrowingDestructorTransaction<TransactionInterface>;
|
||||||
@@ -322,10 +360,11 @@ template<typename BaseTransaction>
|
|||||||
class BasicExclusiveTransaction : public BaseTransaction
|
class BasicExclusiveTransaction : public BaseTransaction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BasicExclusiveTransaction(typename BaseTransaction::Transaction &transactionInterface)
|
BasicExclusiveTransaction(typename BaseTransaction::Transaction &transactionInterface,
|
||||||
: BaseTransaction(transactionInterface)
|
const source_location &sourceLocation = source_location::current())
|
||||||
|
: BaseTransaction(transactionInterface, sourceLocation)
|
||||||
{
|
{
|
||||||
transactionInterface.exclusiveBegin();
|
transactionInterface.exclusiveBegin(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
~BasicExclusiveTransaction()
|
~BasicExclusiveTransaction()
|
||||||
@@ -344,6 +383,9 @@ public:
|
|||||||
using Base::Base;
|
using Base::Base;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename TransactionInterface>
|
||||||
|
ExclusiveTransaction(TransactionInterface &, const source_location &)
|
||||||
|
-> ExclusiveTransaction<TransactionInterface>;
|
||||||
template<typename TransactionInterface>
|
template<typename TransactionInterface>
|
||||||
ExclusiveTransaction(TransactionInterface &) -> ExclusiveTransaction<TransactionInterface>;
|
ExclusiveTransaction(TransactionInterface &) -> ExclusiveTransaction<TransactionInterface>;
|
||||||
|
|
||||||
@@ -357,6 +399,9 @@ public:
|
|||||||
using Base::Base;
|
using Base::Base;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename TransactionInterface>
|
||||||
|
ExclusiveNonThrowingDestructorTransaction(TransactionInterface &, const source_location &)
|
||||||
|
-> ExclusiveNonThrowingDestructorTransaction<TransactionInterface>;
|
||||||
template<typename TransactionInterface>
|
template<typename TransactionInterface>
|
||||||
ExclusiveNonThrowingDestructorTransaction(TransactionInterface &)
|
ExclusiveNonThrowingDestructorTransaction(TransactionInterface &)
|
||||||
-> ExclusiveNonThrowingDestructorTransaction<TransactionInterface>;
|
-> ExclusiveNonThrowingDestructorTransaction<TransactionInterface>;
|
||||||
@@ -368,17 +413,20 @@ class ImmediateSessionTransaction final
|
|||||||
using Base = AbstractThrowingSessionTransaction<TransactionInterface>;
|
using Base = AbstractThrowingSessionTransaction<TransactionInterface>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ImmediateSessionTransaction(typename Base::Transaction &transactionInterface)
|
ImmediateSessionTransaction(typename Base::Transaction &transactionInterface,
|
||||||
: AbstractThrowingSessionTransaction<TransactionInterface>(transactionInterface)
|
const source_location &sourceLocation = source_location::current())
|
||||||
|
: AbstractThrowingSessionTransaction<TransactionInterface>(transactionInterface, sourceLocation)
|
||||||
{
|
{
|
||||||
transactionInterface.immediateSessionBegin();
|
transactionInterface.immediateSessionBegin(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
~ImmediateSessionTransaction() { Base::m_rollback = !Base::m_isAlreadyCommited; }
|
~ImmediateSessionTransaction() { Base::m_rollback = !Base::m_isAlreadyCommited; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename TransactionInterface>
|
||||||
|
ImmediateSessionTransaction(TransactionInterface &, const source_location &)
|
||||||
|
-> ImmediateSessionTransaction<TransactionInterface>;
|
||||||
template<typename TransactionInterface>
|
template<typename TransactionInterface>
|
||||||
ImmediateSessionTransaction(TransactionInterface &)
|
ImmediateSessionTransaction(TransactionInterface &)
|
||||||
-> ImmediateSessionTransaction<TransactionInterface>;
|
-> ImmediateSessionTransaction<TransactionInterface>;
|
||||||
|
|
||||||
} // namespace Sqlite
|
} // namespace Sqlite
|
||||||
|
@@ -12,12 +12,14 @@ class WriteStatement : protected StatementImplementation<BaseStatement, -1, Bind
|
|||||||
using Base = StatementImplementation<BaseStatement, -1, BindParameterCount>;
|
using Base = StatementImplementation<BaseStatement, -1, BindParameterCount>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WriteStatement(Utils::SmallStringView sqlStatement, Database &database)
|
WriteStatement(Utils::SmallStringView sqlStatement,
|
||||||
: Base(sqlStatement, database)
|
Database &database,
|
||||||
|
const source_location &sourceLocation = source_location::current())
|
||||||
|
: Base(sqlStatement, database, sourceLocation)
|
||||||
{
|
{
|
||||||
checkIsWritableStatement();
|
checkIsWritableStatement(sourceLocation);
|
||||||
Base::checkBindingParameterCount(BindParameterCount);
|
Base::checkBindingParameterCount(BindParameterCount, sourceLocation);
|
||||||
Base::checkColumnCount(0);
|
Base::checkColumnCount(0, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
using Base::database;
|
using Base::database;
|
||||||
@@ -25,10 +27,10 @@ public:
|
|||||||
using Base::write;
|
using Base::write;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void checkIsWritableStatement()
|
void checkIsWritableStatement(const source_location &sourceLocation)
|
||||||
{
|
{
|
||||||
if (Base::isReadOnlyStatement())
|
if (Base::isReadOnlyStatement())
|
||||||
throw NotWriteSqlStatement();
|
throw NotWriteSqlStatement(sourceLocation);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -11,6 +11,9 @@
|
|||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
constexpr auto sourceLocation = Sqlite::source_location::current();
|
||||||
|
|
||||||
struct Initializer
|
struct Initializer
|
||||||
{
|
{
|
||||||
Initializer(Sqlite::Database &database, bool isInitialized)
|
Initializer(Sqlite::Database &database, bool isInitialized)
|
||||||
@@ -34,7 +37,7 @@ struct Initializer
|
|||||||
|
|
||||||
table.addPrimaryKeyContraint({filePathColumn, idColumn, keyColumn});
|
table.addPrimaryKeyContraint({filePathColumn, idColumn, keyColumn});
|
||||||
|
|
||||||
table.initialize(database);
|
table.initialize(database, sourceLocation);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -2267,7 +2267,7 @@ SmallSourceIds<32> ProjectStorage::fetchSubdirectorySourceIds(SourceId directory
|
|||||||
|
|
||||||
void ProjectStorage::setPropertyEditorPathId(TypeId typeId, SourceId pathId)
|
void ProjectStorage::setPropertyEditorPathId(TypeId typeId, SourceId pathId)
|
||||||
{
|
{
|
||||||
Sqlite::ImmediateSessionTransaction transaction{database};
|
Sqlite::ImmediateTransaction transaction{database};
|
||||||
|
|
||||||
s->upsertPropertyEditorPathIdStatement.write(typeId, pathId);
|
s->upsertPropertyEditorPathIdStatement.write(typeId, pathId);
|
||||||
|
|
||||||
|
@@ -19,8 +19,8 @@ public:
|
|||||||
: m_databaseMock{&databaseMock}
|
: m_databaseMock{&databaseMock}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
MOCK_METHOD0(next, bool());
|
MOCK_METHOD(bool, next, (const Sqlite::source_location &sourceLocation));
|
||||||
MOCK_METHOD0(step, void ());
|
MOCK_METHOD(void, step, (const Sqlite::source_location &sourceLocation));
|
||||||
MOCK_METHOD0(reset, void ());
|
MOCK_METHOD0(reset, void ());
|
||||||
|
|
||||||
MOCK_CONST_METHOD1(fetchIntValue, int (int));
|
MOCK_CONST_METHOD1(fetchIntValue, int (int));
|
||||||
@@ -35,16 +35,20 @@ public:
|
|||||||
template<typename Type>
|
template<typename Type>
|
||||||
Type fetchValue(int column) const;
|
Type fetchValue(int column) const;
|
||||||
|
|
||||||
MOCK_METHOD2(bind, void (int, int));
|
MOCK_METHOD(void, bind, (int, int, const Sqlite::source_location &sourceLocation));
|
||||||
MOCK_METHOD2(bind, void (int, long long));
|
MOCK_METHOD(void, bind, (int, long long, const Sqlite::source_location &sourceLocation));
|
||||||
MOCK_METHOD2(bind, void (int, double));
|
MOCK_METHOD(void, bind, (int, double, const Sqlite::source_location &sourceLocation));
|
||||||
MOCK_METHOD2(bind, void (int, Utils::SmallStringView));
|
MOCK_METHOD(void,
|
||||||
MOCK_METHOD2(bind, void (int, long));
|
bind,
|
||||||
|
(int, Utils::SmallStringView, const Sqlite::source_location &sourceLocation));
|
||||||
|
MOCK_METHOD(void, bind, (int, long, const Sqlite::source_location &sourceLocation));
|
||||||
|
|
||||||
MOCK_METHOD1(prepare, void(Utils::SmallStringView sqlStatement));
|
MOCK_METHOD(void,
|
||||||
|
prepare,
|
||||||
|
(Utils::SmallStringView sqlStatement, const Sqlite::source_location &sourceLocation));
|
||||||
|
|
||||||
MOCK_METHOD1(checkColumnCount, void(int));
|
MOCK_METHOD(void, checkColumnCount, (int, const Sqlite::source_location &sourceLocation));
|
||||||
MOCK_METHOD1(checkBindingParameterCount, void(int));
|
MOCK_METHOD(void, checkBindingParameterCount, (int, const Sqlite::source_location &sourceLocation));
|
||||||
|
|
||||||
MOCK_CONST_METHOD0(isReadOnlyStatement, bool());
|
MOCK_CONST_METHOD0(isReadOnlyStatement, bool());
|
||||||
|
|
||||||
|
@@ -11,14 +11,14 @@
|
|||||||
class MockSqliteTransactionBackend : public Sqlite::TransactionInterface
|
class MockSqliteTransactionBackend : public Sqlite::TransactionInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MOCK_METHOD0(deferredBegin, void ());
|
MOCK_METHOD(void, deferredBegin, (const Sqlite::source_location &sourceLocation));
|
||||||
MOCK_METHOD0(immediateBegin, void ());
|
MOCK_METHOD(void, immediateBegin, (const Sqlite::source_location &sourceLocation));
|
||||||
MOCK_METHOD0(exclusiveBegin, void ());
|
MOCK_METHOD(void, exclusiveBegin, (const Sqlite::source_location &sourceLocation));
|
||||||
MOCK_METHOD0(commit, void ());
|
MOCK_METHOD(void, commit, (const Sqlite::source_location &sourceLocation));
|
||||||
MOCK_METHOD0(rollback, void ());
|
MOCK_METHOD(void, rollback, (const Sqlite::source_location &sourceLocation));
|
||||||
MOCK_METHOD0(lock, void ());
|
MOCK_METHOD(void, lock, ());
|
||||||
MOCK_METHOD0(unlock, void ());
|
MOCK_METHOD(void, unlock, ());
|
||||||
MOCK_METHOD0(immediateSessionBegin, void());
|
MOCK_METHOD(void, immediateSessionBegin, (const Sqlite::source_location &sourceLocation));
|
||||||
MOCK_METHOD0(sessionCommit, void());
|
MOCK_METHOD(void, sessionCommit, (const Sqlite::source_location &sourceLocation));
|
||||||
MOCK_METHOD0(sessionRollback, void());
|
MOCK_METHOD(void, sessionRollback, (const Sqlite::source_location &sourceLocation));
|
||||||
};
|
};
|
||||||
|
@@ -28,7 +28,15 @@ public:
|
|||||||
|
|
||||||
MOCK_METHOD(void, prepare, (Utils::SmallStringView sqlStatement), ());
|
MOCK_METHOD(void, prepare, (Utils::SmallStringView sqlStatement), ());
|
||||||
|
|
||||||
MOCK_METHOD(void, execute, (Utils::SmallStringView sqlStatement), (override));
|
MOCK_METHOD(void,
|
||||||
|
execute,
|
||||||
|
(Utils::SmallStringView sqlStatement, const Sqlite::source_location &sourceLocation),
|
||||||
|
(override));
|
||||||
|
|
||||||
|
void execute(Utils::SmallStringView sqlStatement)
|
||||||
|
{
|
||||||
|
execute(sqlStatement, Sqlite::source_location::current());
|
||||||
|
}
|
||||||
|
|
||||||
MOCK_METHOD(int64_t, lastInsertedRowId, (), (const));
|
MOCK_METHOD(int64_t, lastInsertedRowId, (), (const));
|
||||||
|
|
||||||
@@ -41,7 +49,9 @@ public:
|
|||||||
|
|
||||||
MOCK_METHOD(void, setIsInitialized, (bool), ());
|
MOCK_METHOD(void, setIsInitialized, (bool), ());
|
||||||
|
|
||||||
MOCK_METHOD(void, walCheckpointFull, (), (override));
|
MOCK_METHOD(void, walCheckpointFull, (const Sqlite::source_location &sourceLocation), (override));
|
||||||
|
|
||||||
|
void walCheckpointFull() { walCheckpointFull(Sqlite::source_location::current()); }
|
||||||
|
|
||||||
MOCK_METHOD(void,
|
MOCK_METHOD(void,
|
||||||
setUpdateHook,
|
setUpdateHook,
|
||||||
|
@@ -11,14 +11,14 @@
|
|||||||
class SqliteTransactionBackendMock : public Sqlite::TransactionInterface
|
class SqliteTransactionBackendMock : public Sqlite::TransactionInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MOCK_METHOD(void, deferredBegin, (), (override));
|
MOCK_METHOD(void, deferredBegin, (const Sqlite::source_location &sourceLocation), (override));
|
||||||
MOCK_METHOD(void, immediateBegin, (), (override));
|
MOCK_METHOD(void, immediateBegin, (const Sqlite::source_location &sourceLocation), (override));
|
||||||
MOCK_METHOD(void, exclusiveBegin, (), (override));
|
MOCK_METHOD(void, exclusiveBegin, (const Sqlite::source_location &sourceLocation), (override));
|
||||||
MOCK_METHOD(void, commit, (), (override));
|
MOCK_METHOD(void, commit, (const Sqlite::source_location &sourceLocation), (override));
|
||||||
MOCK_METHOD(void, rollback, (), (override));
|
MOCK_METHOD(void, rollback, (const Sqlite::source_location &sourceLocation), (override));
|
||||||
MOCK_METHOD(void, lock, (), (override));
|
MOCK_METHOD(void, lock, (), (override));
|
||||||
MOCK_METHOD(void, unlock, (), (override));
|
MOCK_METHOD(void, unlock, (), (override));
|
||||||
MOCK_METHOD(void, immediateSessionBegin, (), (override));
|
MOCK_METHOD(void, immediateSessionBegin, (const Sqlite::source_location &sourceLocation), (override));
|
||||||
MOCK_METHOD(void, sessionCommit, (), (override));
|
MOCK_METHOD(void, sessionCommit, (const Sqlite::source_location &sourceLocation), (override));
|
||||||
MOCK_METHOD(void, sessionRollback, (), (override));
|
MOCK_METHOD(void, sessionRollback, (const Sqlite::source_location &sourceLocation), (override));
|
||||||
};
|
};
|
||||||
|
@@ -29,9 +29,9 @@ TEST(ImageCacheStorageUpdateTest, add_column_mid_size_if_version_is_zero)
|
|||||||
{
|
{
|
||||||
NiceMock<SqliteDatabaseMock> databaseMock;
|
NiceMock<SqliteDatabaseMock> databaseMock;
|
||||||
ON_CALL(databaseMock, isInitialized()).WillByDefault(Return(true));
|
ON_CALL(databaseMock, isInitialized()).WillByDefault(Return(true));
|
||||||
EXPECT_CALL(databaseMock, execute(_)).Times(AnyNumber());
|
EXPECT_CALL(databaseMock, execute(_, _)).Times(AnyNumber());
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, execute(Eq("ALTER TABLE images ADD COLUMN midSizeImage")));
|
EXPECT_CALL(databaseMock, execute(Eq("ALTER TABLE images ADD COLUMN midSizeImage"), _));
|
||||||
|
|
||||||
QmlDesigner::ImageCacheStorage<SqliteDatabaseMock> storage{databaseMock};
|
QmlDesigner::ImageCacheStorage<SqliteDatabaseMock> storage{databaseMock};
|
||||||
}
|
}
|
||||||
@@ -42,8 +42,8 @@ TEST(ImageCacheStorageUpdateTest, delete_all_rows_before_adding_mid_size_column)
|
|||||||
ON_CALL(databaseMock, isInitialized()).WillByDefault(Return(true));
|
ON_CALL(databaseMock, isInitialized()).WillByDefault(Return(true));
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, execute(Eq("DELETE FROM images")));
|
EXPECT_CALL(databaseMock, execute(Eq("DELETE FROM images"), _));
|
||||||
EXPECT_CALL(databaseMock, execute(Eq("ALTER TABLE images ADD COLUMN midSizeImage")));
|
EXPECT_CALL(databaseMock, execute(Eq("ALTER TABLE images ADD COLUMN midSizeImage"), _));
|
||||||
|
|
||||||
QmlDesigner::ImageCacheStorage<SqliteDatabaseMock> storage{databaseMock};
|
QmlDesigner::ImageCacheStorage<SqliteDatabaseMock> storage{databaseMock};
|
||||||
}
|
}
|
||||||
@@ -52,9 +52,9 @@ TEST(ImageCacheStorageUpdateTest, dont_call_add_column_mid_size_if_database_was_
|
|||||||
{
|
{
|
||||||
NiceMock<SqliteDatabaseMock> databaseMock;
|
NiceMock<SqliteDatabaseMock> databaseMock;
|
||||||
ON_CALL(databaseMock, isInitialized()).WillByDefault(Return(false));
|
ON_CALL(databaseMock, isInitialized()).WillByDefault(Return(false));
|
||||||
EXPECT_CALL(databaseMock, execute(_)).Times(2);
|
EXPECT_CALL(databaseMock, execute(_, _)).Times(2);
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, execute(Eq("ALTER TABLE images ADD COLUMN midSizeImage"))).Times(0);
|
EXPECT_CALL(databaseMock, execute(Eq("ALTER TABLE images ADD COLUMN midSizeImage"), _)).Times(0);
|
||||||
|
|
||||||
QmlDesigner::ImageCacheStorage<SqliteDatabaseMock> storage{databaseMock};
|
QmlDesigner::ImageCacheStorage<SqliteDatabaseMock> storage{databaseMock};
|
||||||
}
|
}
|
||||||
@@ -118,11 +118,11 @@ TEST_F(ImageCacheStorageTest, fetch_image_calls)
|
|||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, deferredBegin());
|
EXPECT_CALL(databaseMock, deferredBegin(_));
|
||||||
EXPECT_CALL(selectImageStatement,
|
EXPECT_CALL(selectImageStatement,
|
||||||
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
TypedEq<long long>(123)));
|
TypedEq<long long>(123)));
|
||||||
EXPECT_CALL(databaseMock, commit());
|
EXPECT_CALL(databaseMock, commit(_));
|
||||||
|
|
||||||
storage.fetchImage("/path/to/component", {123});
|
storage.fetchImage("/path/to/component", {123});
|
||||||
}
|
}
|
||||||
@@ -131,17 +131,17 @@ TEST_F(ImageCacheStorageTest, fetch_image_calls_is_busy)
|
|||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, deferredBegin());
|
EXPECT_CALL(databaseMock, deferredBegin(_));
|
||||||
EXPECT_CALL(selectImageStatement,
|
EXPECT_CALL(selectImageStatement,
|
||||||
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
TypedEq<long long>(123)))
|
TypedEq<long long>(123)))
|
||||||
.WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
|
.WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
|
||||||
EXPECT_CALL(databaseMock, rollback());
|
EXPECT_CALL(databaseMock, rollback(_));
|
||||||
EXPECT_CALL(databaseMock, deferredBegin());
|
EXPECT_CALL(databaseMock, deferredBegin(_));
|
||||||
EXPECT_CALL(selectImageStatement,
|
EXPECT_CALL(selectImageStatement,
|
||||||
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
TypedEq<long long>(123)));
|
TypedEq<long long>(123)));
|
||||||
EXPECT_CALL(databaseMock, commit());
|
EXPECT_CALL(databaseMock, commit(_));
|
||||||
|
|
||||||
storage.fetchImage("/path/to/component", {123});
|
storage.fetchImage("/path/to/component", {123});
|
||||||
}
|
}
|
||||||
@@ -150,11 +150,11 @@ TEST_F(ImageCacheStorageTest, fetch_mid_size_image_calls)
|
|||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, deferredBegin());
|
EXPECT_CALL(databaseMock, deferredBegin(_));
|
||||||
EXPECT_CALL(selectMidSizeImageStatement,
|
EXPECT_CALL(selectMidSizeImageStatement,
|
||||||
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
TypedEq<long long>(123)));
|
TypedEq<long long>(123)));
|
||||||
EXPECT_CALL(databaseMock, commit());
|
EXPECT_CALL(databaseMock, commit(_));
|
||||||
|
|
||||||
storage.fetchMidSizeImage("/path/to/component", {123});
|
storage.fetchMidSizeImage("/path/to/component", {123});
|
||||||
}
|
}
|
||||||
@@ -163,17 +163,17 @@ TEST_F(ImageCacheStorageTest, fetch_mid_size_image_calls_is_busy)
|
|||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, deferredBegin());
|
EXPECT_CALL(databaseMock, deferredBegin(_));
|
||||||
EXPECT_CALL(selectMidSizeImageStatement,
|
EXPECT_CALL(selectMidSizeImageStatement,
|
||||||
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
TypedEq<long long>(123)))
|
TypedEq<long long>(123)))
|
||||||
.WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
|
.WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
|
||||||
EXPECT_CALL(databaseMock, rollback());
|
EXPECT_CALL(databaseMock, rollback(_));
|
||||||
EXPECT_CALL(databaseMock, deferredBegin());
|
EXPECT_CALL(databaseMock, deferredBegin(_));
|
||||||
EXPECT_CALL(selectMidSizeImageStatement,
|
EXPECT_CALL(selectMidSizeImageStatement,
|
||||||
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
TypedEq<long long>(123)));
|
TypedEq<long long>(123)));
|
||||||
EXPECT_CALL(databaseMock, commit());
|
EXPECT_CALL(databaseMock, commit(_));
|
||||||
|
|
||||||
storage.fetchMidSizeImage("/path/to/component", {123});
|
storage.fetchMidSizeImage("/path/to/component", {123});
|
||||||
}
|
}
|
||||||
@@ -182,11 +182,11 @@ TEST_F(ImageCacheStorageTest, fetch_small_image_calls)
|
|||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, deferredBegin());
|
EXPECT_CALL(databaseMock, deferredBegin(_));
|
||||||
EXPECT_CALL(selectSmallImageStatement,
|
EXPECT_CALL(selectSmallImageStatement,
|
||||||
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
TypedEq<long long>(123)));
|
TypedEq<long long>(123)));
|
||||||
EXPECT_CALL(databaseMock, commit());
|
EXPECT_CALL(databaseMock, commit(_));
|
||||||
|
|
||||||
storage.fetchSmallImage("/path/to/component", {123});
|
storage.fetchSmallImage("/path/to/component", {123});
|
||||||
}
|
}
|
||||||
@@ -195,17 +195,17 @@ TEST_F(ImageCacheStorageTest, fetch_small_image_calls_is_busy)
|
|||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, deferredBegin());
|
EXPECT_CALL(databaseMock, deferredBegin(_));
|
||||||
EXPECT_CALL(selectSmallImageStatement,
|
EXPECT_CALL(selectSmallImageStatement,
|
||||||
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
TypedEq<long long>(123)))
|
TypedEq<long long>(123)))
|
||||||
.WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
|
.WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
|
||||||
EXPECT_CALL(databaseMock, rollback());
|
EXPECT_CALL(databaseMock, rollback(_));
|
||||||
EXPECT_CALL(databaseMock, deferredBegin());
|
EXPECT_CALL(databaseMock, deferredBegin(_));
|
||||||
EXPECT_CALL(selectSmallImageStatement,
|
EXPECT_CALL(selectSmallImageStatement,
|
||||||
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
TypedEq<long long>(123)));
|
TypedEq<long long>(123)));
|
||||||
EXPECT_CALL(databaseMock, commit());
|
EXPECT_CALL(databaseMock, commit(_));
|
||||||
|
|
||||||
storage.fetchSmallImage("/path/to/component", {123});
|
storage.fetchSmallImage("/path/to/component", {123});
|
||||||
}
|
}
|
||||||
@@ -214,11 +214,11 @@ TEST_F(ImageCacheStorageTest, fetch_icon_calls)
|
|||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, deferredBegin());
|
EXPECT_CALL(databaseMock, deferredBegin(_));
|
||||||
EXPECT_CALL(selectIconStatement,
|
EXPECT_CALL(selectIconStatement,
|
||||||
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
TypedEq<long long>(123)));
|
TypedEq<long long>(123)));
|
||||||
EXPECT_CALL(databaseMock, commit());
|
EXPECT_CALL(databaseMock, commit(_));
|
||||||
|
|
||||||
storage.fetchIcon("/path/to/component", {123});
|
storage.fetchIcon("/path/to/component", {123});
|
||||||
}
|
}
|
||||||
@@ -227,17 +227,17 @@ TEST_F(ImageCacheStorageTest, fetch_icon_calls_is_busy)
|
|||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, deferredBegin());
|
EXPECT_CALL(databaseMock, deferredBegin(_));
|
||||||
EXPECT_CALL(selectIconStatement,
|
EXPECT_CALL(selectIconStatement,
|
||||||
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
TypedEq<long long>(123)))
|
TypedEq<long long>(123)))
|
||||||
.WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
|
.WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
|
||||||
EXPECT_CALL(databaseMock, rollback());
|
EXPECT_CALL(databaseMock, rollback(_));
|
||||||
EXPECT_CALL(databaseMock, deferredBegin());
|
EXPECT_CALL(databaseMock, deferredBegin(_));
|
||||||
EXPECT_CALL(selectIconStatement,
|
EXPECT_CALL(selectIconStatement,
|
||||||
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
TypedEq<long long>(123)));
|
TypedEq<long long>(123)));
|
||||||
EXPECT_CALL(databaseMock, commit());
|
EXPECT_CALL(databaseMock, commit(_));
|
||||||
|
|
||||||
storage.fetchIcon("/path/to/component", {123});
|
storage.fetchIcon("/path/to/component", {123});
|
||||||
}
|
}
|
||||||
@@ -246,14 +246,14 @@ TEST_F(ImageCacheStorageTest, store_image_calls)
|
|||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, immediateBegin());
|
EXPECT_CALL(databaseMock, immediateBegin(_));
|
||||||
EXPECT_CALL(upsertImageStatement,
|
EXPECT_CALL(upsertImageStatement,
|
||||||
write(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
write(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
TypedEq<long long>(123),
|
TypedEq<long long>(123),
|
||||||
Not(IsEmpty()),
|
Not(IsEmpty()),
|
||||||
Not(IsEmpty()),
|
Not(IsEmpty()),
|
||||||
Not(IsEmpty())));
|
Not(IsEmpty())));
|
||||||
EXPECT_CALL(databaseMock, commit());
|
EXPECT_CALL(databaseMock, commit(_));
|
||||||
|
|
||||||
storage.storeImage("/path/to/component", {123}, image1, midSizeImage1, smallImage1);
|
storage.storeImage("/path/to/component", {123}, image1, midSizeImage1, smallImage1);
|
||||||
}
|
}
|
||||||
@@ -262,14 +262,14 @@ TEST_F(ImageCacheStorageTest, store_empty_image_calls)
|
|||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, immediateBegin());
|
EXPECT_CALL(databaseMock, immediateBegin(_));
|
||||||
EXPECT_CALL(upsertImageStatement,
|
EXPECT_CALL(upsertImageStatement,
|
||||||
write(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
write(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
TypedEq<long long>(123),
|
TypedEq<long long>(123),
|
||||||
IsEmpty(),
|
IsEmpty(),
|
||||||
IsEmpty(),
|
IsEmpty(),
|
||||||
IsEmpty()));
|
IsEmpty()));
|
||||||
EXPECT_CALL(databaseMock, commit());
|
EXPECT_CALL(databaseMock, commit(_));
|
||||||
|
|
||||||
storage.storeImage("/path/to/component", {123}, QImage{}, QImage{}, QImage{});
|
storage.storeImage("/path/to/component", {123}, QImage{}, QImage{}, QImage{});
|
||||||
}
|
}
|
||||||
@@ -278,15 +278,15 @@ TEST_F(ImageCacheStorageTest, store_image_calls_is_busy)
|
|||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
|
EXPECT_CALL(databaseMock, immediateBegin(_)).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
|
||||||
EXPECT_CALL(databaseMock, immediateBegin());
|
EXPECT_CALL(databaseMock, immediateBegin(_));
|
||||||
EXPECT_CALL(upsertImageStatement,
|
EXPECT_CALL(upsertImageStatement,
|
||||||
write(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
write(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
TypedEq<long long>(123),
|
TypedEq<long long>(123),
|
||||||
IsEmpty(),
|
IsEmpty(),
|
||||||
IsEmpty(),
|
IsEmpty(),
|
||||||
IsEmpty()));
|
IsEmpty()));
|
||||||
EXPECT_CALL(databaseMock, commit());
|
EXPECT_CALL(databaseMock, commit(_));
|
||||||
|
|
||||||
storage.storeImage("/path/to/component", {123}, QImage{}, QImage{}, QImage{});
|
storage.storeImage("/path/to/component", {123}, QImage{}, QImage{}, QImage{});
|
||||||
}
|
}
|
||||||
@@ -295,12 +295,12 @@ TEST_F(ImageCacheStorageTest, store_icon_calls)
|
|||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, immediateBegin());
|
EXPECT_CALL(databaseMock, immediateBegin(_));
|
||||||
EXPECT_CALL(upsertIconStatement,
|
EXPECT_CALL(upsertIconStatement,
|
||||||
write(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
write(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
TypedEq<long long>(123),
|
TypedEq<long long>(123),
|
||||||
A<Sqlite::BlobView>()));
|
A<Sqlite::BlobView>()));
|
||||||
EXPECT_CALL(databaseMock, commit());
|
EXPECT_CALL(databaseMock, commit(_));
|
||||||
|
|
||||||
storage.storeIcon("/path/to/component", {123}, icon1);
|
storage.storeIcon("/path/to/component", {123}, icon1);
|
||||||
}
|
}
|
||||||
@@ -309,12 +309,12 @@ TEST_F(ImageCacheStorageTest, store_empty_icon_calls)
|
|||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, immediateBegin());
|
EXPECT_CALL(databaseMock, immediateBegin(_));
|
||||||
EXPECT_CALL(upsertIconStatement,
|
EXPECT_CALL(upsertIconStatement,
|
||||||
write(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
write(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
TypedEq<long long>(123),
|
TypedEq<long long>(123),
|
||||||
IsEmpty()));
|
IsEmpty()));
|
||||||
EXPECT_CALL(databaseMock, commit());
|
EXPECT_CALL(databaseMock, commit(_));
|
||||||
|
|
||||||
storage.storeIcon("/path/to/component", {123}, QIcon{});
|
storage.storeIcon("/path/to/component", {123}, QIcon{});
|
||||||
}
|
}
|
||||||
@@ -323,20 +323,20 @@ TEST_F(ImageCacheStorageTest, store_icon_calls_is_busy)
|
|||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
|
EXPECT_CALL(databaseMock, immediateBegin(_)).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
|
||||||
EXPECT_CALL(databaseMock, immediateBegin());
|
EXPECT_CALL(databaseMock, immediateBegin(_));
|
||||||
EXPECT_CALL(upsertIconStatement,
|
EXPECT_CALL(upsertIconStatement,
|
||||||
write(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
write(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
TypedEq<long long>(123),
|
TypedEq<long long>(123),
|
||||||
IsEmpty()));
|
IsEmpty()));
|
||||||
EXPECT_CALL(databaseMock, commit());
|
EXPECT_CALL(databaseMock, commit(_));
|
||||||
|
|
||||||
storage.storeIcon("/path/to/component", {123}, QIcon{});
|
storage.storeIcon("/path/to/component", {123}, QIcon{});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ImageCacheStorageTest, call_wal_checkoint_full)
|
TEST_F(ImageCacheStorageTest, call_wal_checkoint_full)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(databaseMock, walCheckpointFull());
|
EXPECT_CALL(databaseMock, walCheckpointFull(_));
|
||||||
|
|
||||||
storage.walCheckpointFull();
|
storage.walCheckpointFull();
|
||||||
}
|
}
|
||||||
@@ -345,8 +345,8 @@ TEST_F(ImageCacheStorageTest, call_wal_checkoint_full_is_busy)
|
|||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, walCheckpointFull()).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
|
EXPECT_CALL(databaseMock, walCheckpointFull(_)).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
|
||||||
EXPECT_CALL(databaseMock, walCheckpointFull());
|
EXPECT_CALL(databaseMock, walCheckpointFull(_));
|
||||||
|
|
||||||
storage.walCheckpointFull();
|
storage.walCheckpointFull();
|
||||||
}
|
}
|
||||||
|
@@ -26,6 +26,8 @@ using Sqlite::JournalMode;
|
|||||||
using Sqlite::OpenMode;
|
using Sqlite::OpenMode;
|
||||||
using Sqlite::Table;
|
using Sqlite::Table;
|
||||||
|
|
||||||
|
constexpr auto sourceLocation = Sqlite::source_location::current();
|
||||||
|
|
||||||
class SqliteDatabase : public ::testing::Test
|
class SqliteDatabase : public ::testing::Test
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@@ -199,37 +201,37 @@ TEST_F(SqliteDatabase, last_row_id)
|
|||||||
|
|
||||||
TEST_F(SqliteDatabase, deferred_begin)
|
TEST_F(SqliteDatabase, deferred_begin)
|
||||||
{
|
{
|
||||||
ASSERT_NO_THROW(transactionInterface.deferredBegin());
|
ASSERT_NO_THROW(transactionInterface.deferredBegin(sourceLocation));
|
||||||
|
|
||||||
transactionInterface.commit();
|
transactionInterface.commit(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteDatabase, immediate_begin)
|
TEST_F(SqliteDatabase, immediate_begin)
|
||||||
{
|
{
|
||||||
ASSERT_NO_THROW(transactionInterface.immediateBegin());
|
ASSERT_NO_THROW(transactionInterface.immediateBegin(sourceLocation));
|
||||||
|
|
||||||
transactionInterface.commit();
|
transactionInterface.commit(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteDatabase, exclusive_begin)
|
TEST_F(SqliteDatabase, exclusive_begin)
|
||||||
{
|
{
|
||||||
ASSERT_NO_THROW(transactionInterface.exclusiveBegin());
|
ASSERT_NO_THROW(transactionInterface.exclusiveBegin(sourceLocation));
|
||||||
|
|
||||||
transactionInterface.commit();
|
transactionInterface.commit(sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteDatabase, commit)
|
TEST_F(SqliteDatabase, commit)
|
||||||
{
|
{
|
||||||
transactionInterface.deferredBegin();
|
transactionInterface.deferredBegin(sourceLocation);
|
||||||
|
|
||||||
ASSERT_NO_THROW(transactionInterface.commit());
|
ASSERT_NO_THROW(transactionInterface.commit(sourceLocation));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteDatabase, rollback)
|
TEST_F(SqliteDatabase, rollback)
|
||||||
{
|
{
|
||||||
transactionInterface.deferredBegin();
|
transactionInterface.deferredBegin(sourceLocation);
|
||||||
|
|
||||||
ASSERT_NO_THROW(transactionInterface.rollback());
|
ASSERT_NO_THROW(transactionInterface.rollback(sourceLocation));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteDatabase, set_update_hook_set)
|
TEST_F(SqliteDatabase, set_update_hook_set)
|
||||||
|
@@ -24,6 +24,8 @@ using Sqlite::OpenMode;
|
|||||||
using Sqlite::Exception;
|
using Sqlite::Exception;
|
||||||
using Sqlite::WriteStatement;
|
using Sqlite::WriteStatement;
|
||||||
|
|
||||||
|
constexpr auto sourceLocation = Sqlite::source_location::current();
|
||||||
|
|
||||||
class SqliteDatabaseBackend : public ::testing::Test
|
class SqliteDatabaseBackend : public ::testing::Test
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@@ -31,7 +33,10 @@ protected:
|
|||||||
{
|
{
|
||||||
database.lock();
|
database.lock();
|
||||||
QDir::temp().remove(QStringLiteral("SqliteDatabaseBackendTest.db"));
|
QDir::temp().remove(QStringLiteral("SqliteDatabaseBackendTest.db"));
|
||||||
databaseBackend.open(databaseFilePath, OpenMode::ReadWrite, Sqlite::JournalMode::Wal);
|
databaseBackend.open(databaseFilePath,
|
||||||
|
OpenMode::ReadWrite,
|
||||||
|
Sqlite::JournalMode::Wal,
|
||||||
|
sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
~SqliteDatabaseBackend() noexcept(true)
|
~SqliteDatabaseBackend() noexcept(true)
|
||||||
@@ -49,56 +54,60 @@ using SqliteDatabaseBackendSlowTest = SqliteDatabaseBackend;
|
|||||||
|
|
||||||
TEST_F(SqliteDatabaseBackend, open_already_open_database)
|
TEST_F(SqliteDatabaseBackend, open_already_open_database)
|
||||||
{
|
{
|
||||||
ASSERT_THROW(databaseBackend.open(databaseFilePath, OpenMode::ReadWrite, Sqlite::JournalMode::Wal),
|
ASSERT_THROW(databaseBackend.open(databaseFilePath,
|
||||||
|
OpenMode::ReadWrite,
|
||||||
|
Sqlite::JournalMode::Wal,
|
||||||
|
sourceLocation),
|
||||||
Sqlite::DatabaseIsAlreadyOpen);
|
Sqlite::DatabaseIsAlreadyOpen);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteDatabaseBackend, close_already_closed_database)
|
TEST_F(SqliteDatabaseBackend, close_already_closed_database)
|
||||||
{
|
{
|
||||||
databaseBackend.close();
|
databaseBackend.close(sourceLocation);
|
||||||
|
|
||||||
ASSERT_THROW(databaseBackend.close(), Sqlite::DatabaseIsAlreadyClosed);
|
ASSERT_THROW(databaseBackend.close(sourceLocation), Sqlite::DatabaseIsAlreadyClosed);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteDatabaseBackend, open_with_wrong_path)
|
TEST_F(SqliteDatabaseBackend, open_with_wrong_path)
|
||||||
{
|
{
|
||||||
ASSERT_THROW(databaseBackend.open("/xxx/SqliteDatabaseBackendTest.db",
|
ASSERT_THROW(databaseBackend.open("/xxx/SqliteDatabaseBackendTest.db",
|
||||||
OpenMode::ReadWrite,
|
OpenMode::ReadWrite,
|
||||||
Sqlite::JournalMode::Wal),
|
Sqlite::JournalMode::Wal,
|
||||||
|
sourceLocation),
|
||||||
Sqlite::WrongFilePath);
|
Sqlite::WrongFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteDatabaseBackend, default_journal_mode)
|
TEST_F(SqliteDatabaseBackend, default_journal_mode)
|
||||||
{
|
{
|
||||||
ASSERT_THAT(databaseBackend.journalMode(), JournalMode::Delete);
|
ASSERT_THAT(databaseBackend.journalMode(sourceLocation), JournalMode::Delete);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteDatabaseBackendSlowTest, wal_journal_mode)
|
TEST_F(SqliteDatabaseBackendSlowTest, wal_journal_mode)
|
||||||
{
|
{
|
||||||
databaseBackend.setJournalMode(JournalMode::Wal);
|
databaseBackend.setJournalMode(JournalMode::Wal, sourceLocation);
|
||||||
|
|
||||||
ASSERT_THAT(databaseBackend.journalMode(), JournalMode::Wal);
|
ASSERT_THAT(databaseBackend.journalMode(sourceLocation), JournalMode::Wal);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteDatabaseBackend, truncate_journal_mode)
|
TEST_F(SqliteDatabaseBackend, truncate_journal_mode)
|
||||||
{
|
{
|
||||||
databaseBackend.setJournalMode(JournalMode::Truncate);
|
databaseBackend.setJournalMode(JournalMode::Truncate, sourceLocation);
|
||||||
|
|
||||||
ASSERT_THAT(databaseBackend.journalMode(), JournalMode::Truncate);
|
ASSERT_THAT(databaseBackend.journalMode(sourceLocation), JournalMode::Truncate);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteDatabaseBackend, memory_journal_mode)
|
TEST_F(SqliteDatabaseBackend, memory_journal_mode)
|
||||||
{
|
{
|
||||||
databaseBackend.setJournalMode(JournalMode::Memory);
|
databaseBackend.setJournalMode(JournalMode::Memory, sourceLocation);
|
||||||
|
|
||||||
ASSERT_THAT(databaseBackend.journalMode(), JournalMode::Memory);
|
ASSERT_THAT(databaseBackend.journalMode(sourceLocation), JournalMode::Memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteDatabaseBackend, persist_journal_mode)
|
TEST_F(SqliteDatabaseBackend, persist_journal_mode)
|
||||||
{
|
{
|
||||||
databaseBackend.setJournalMode(JournalMode::Persist);
|
databaseBackend.setJournalMode(JournalMode::Persist, sourceLocation);
|
||||||
|
|
||||||
ASSERT_THAT(databaseBackend.journalMode(), JournalMode::Persist);
|
ASSERT_THAT(databaseBackend.journalMode(sourceLocation), JournalMode::Persist);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteDatabaseBackend, open_mode_read_only)
|
TEST_F(SqliteDatabaseBackend, open_mode_read_only)
|
||||||
|
@@ -56,6 +56,8 @@ bool compareValue(SqliteTestStatement<2, 1> &statement, Type value, int column)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr auto sourceLocation = Sqlite::source_location::current();
|
||||||
|
|
||||||
MATCHER_P3(HasValues,
|
MATCHER_P3(HasValues,
|
||||||
value1,
|
value1,
|
||||||
value2,
|
value2,
|
||||||
@@ -66,9 +68,9 @@ MATCHER_P3(HasValues,
|
|||||||
Database &database = arg.database();
|
Database &database = arg.database();
|
||||||
|
|
||||||
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE rowid=?", database);
|
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE rowid=?", database);
|
||||||
statement.bind(1, rowid);
|
statement.bind(1, rowid, sourceLocation);
|
||||||
|
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
return compareValue(statement, value1, 0) && compareValue(statement, value2, 1);
|
return compareValue(statement, value1, 0) && compareValue(statement, value2, 1);
|
||||||
}
|
}
|
||||||
@@ -78,9 +80,9 @@ MATCHER_P(HasNullValues, rowid, std::string(negation ? "isn't null" : "is null")
|
|||||||
Database &database = arg.database();
|
Database &database = arg.database();
|
||||||
|
|
||||||
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE rowid=?", database);
|
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE rowid=?", database);
|
||||||
statement.bind(1, rowid);
|
statement.bind(1, rowid, sourceLocation);
|
||||||
|
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
return statement.fetchValueView(0).isNull() && statement.fetchValueView(1).isNull();
|
return statement.fetchValueView(0).isNull() && statement.fetchValueView(1).isNull();
|
||||||
}
|
}
|
||||||
@@ -163,7 +165,7 @@ TEST_F(SqliteStatement, count_rows)
|
|||||||
{
|
{
|
||||||
SqliteTestStatement<3> statement("SELECT * FROM test", database);
|
SqliteTestStatement<3> statement("SELECT * FROM test", database);
|
||||||
int nextCount = 0;
|
int nextCount = 0;
|
||||||
while (statement.next())
|
while (statement.next(sourceLocation))
|
||||||
++nextCount;
|
++nextCount;
|
||||||
|
|
||||||
int sqlCount = ReadStatement<1>::toValue<int>("SELECT count(*) FROM test", database);
|
int sqlCount = ReadStatement<1>::toValue<int>("SELECT count(*) FROM test", database);
|
||||||
@@ -174,9 +176,9 @@ TEST_F(SqliteStatement, count_rows)
|
|||||||
TEST_F(SqliteStatement, value)
|
TEST_F(SqliteStatement, value)
|
||||||
{
|
{
|
||||||
SqliteTestStatement<3> statement("SELECT name, number, value FROM test ORDER BY name", database);
|
SqliteTestStatement<3> statement("SELECT name, number, value FROM test ORDER BY name", database);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
ASSERT_THAT(statement.fetchValue<int>(0), 0);
|
ASSERT_THAT(statement.fetchValue<int>(0), 0);
|
||||||
ASSERT_THAT(statement.fetchValue<int64_t>(0), 0);
|
ASSERT_THAT(statement.fetchValue<int64_t>(0), 0);
|
||||||
@@ -226,8 +228,8 @@ TEST_F(SqliteStatement, bind_null)
|
|||||||
database.execute("INSERT INTO test VALUES (NULL, 323, 344)");
|
database.execute("INSERT INTO test VALUES (NULL, 323, 344)");
|
||||||
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE name IS ?", database);
|
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE name IS ?", database);
|
||||||
|
|
||||||
statement.bindNull(1);
|
statement.bindNull(1, sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
ASSERT_TRUE(statement.fetchValueView(0).isNull());
|
ASSERT_TRUE(statement.fetchValueView(0).isNull());
|
||||||
ASSERT_THAT(statement.fetchValue<int>(1), 323);
|
ASSERT_THAT(statement.fetchValue<int>(1), 323);
|
||||||
@@ -238,8 +240,8 @@ TEST_F(SqliteStatement, bind_null_value)
|
|||||||
database.execute("INSERT INTO test VALUES (NULL, 323, 344)");
|
database.execute("INSERT INTO test VALUES (NULL, 323, 344)");
|
||||||
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE name IS ?", database);
|
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE name IS ?", database);
|
||||||
|
|
||||||
statement.bind(1, Sqlite::NullValue{});
|
statement.bind(1, Sqlite::NullValue{}, sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
ASSERT_TRUE(statement.fetchValueView(0).isNull());
|
ASSERT_TRUE(statement.fetchValueView(0).isNull());
|
||||||
ASSERT_THAT(statement.fetchValue<int>(1), 323);
|
ASSERT_THAT(statement.fetchValue<int>(1), 323);
|
||||||
@@ -250,11 +252,11 @@ TEST_F(SqliteStatement, bind_invalid_int_id_to_null)
|
|||||||
TestIntId id;
|
TestIntId id;
|
||||||
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
|
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
|
||||||
|
|
||||||
statement.bind(1, id);
|
statement.bind(1, id, sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
|
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
|
||||||
readStatement.next();
|
readStatement.next(sourceLocation);
|
||||||
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Null);
|
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,11 +265,11 @@ TEST_F(SqliteStatement, bind_invalid_compound_id_to_null)
|
|||||||
CompoundId id;
|
CompoundId id;
|
||||||
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
|
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
|
||||||
|
|
||||||
statement.bind(1, id);
|
statement.bind(1, id, sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
|
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
|
||||||
readStatement.next();
|
readStatement.next(sourceLocation);
|
||||||
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Null);
|
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,11 +278,11 @@ TEST_F(SqliteStatement, bind_int_id)
|
|||||||
TestIntId id{TestIntId::create(42)};
|
TestIntId id{TestIntId::create(42)};
|
||||||
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
|
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
|
||||||
|
|
||||||
statement.bind(1, id);
|
statement.bind(1, id, sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
|
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
|
||||||
readStatement.next();
|
readStatement.next(sourceLocation);
|
||||||
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Integer);
|
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Integer);
|
||||||
ASSERT_THAT(readStatement.fetchIntValue(0), 42);
|
ASSERT_THAT(readStatement.fetchIntValue(0), 42);
|
||||||
}
|
}
|
||||||
@@ -290,11 +292,11 @@ TEST_F(SqliteStatement, bind_compound_id)
|
|||||||
CompoundId id = CompoundId::create(42);
|
CompoundId id = CompoundId::create(42);
|
||||||
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
|
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
|
||||||
|
|
||||||
statement.bind(1, id);
|
statement.bind(1, id, sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
|
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
|
||||||
readStatement.next();
|
readStatement.next(sourceLocation);
|
||||||
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Integer);
|
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Integer);
|
||||||
ASSERT_THAT(readStatement.fetchIntValue(0), 42);
|
ASSERT_THAT(readStatement.fetchIntValue(0), 42);
|
||||||
}
|
}
|
||||||
@@ -305,11 +307,11 @@ TEST_F(SqliteStatement, bind_special_state_id)
|
|||||||
constexpr TestIntId unresolvedTypeId = TestIntId::createSpecialState(SpecialIdState::Unresolved);
|
constexpr TestIntId unresolvedTypeId = TestIntId::createSpecialState(SpecialIdState::Unresolved);
|
||||||
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
|
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
|
||||||
|
|
||||||
statement.bind(1, unresolvedTypeId);
|
statement.bind(1, unresolvedTypeId, sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
|
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
|
||||||
readStatement.next();
|
readStatement.next(sourceLocation);
|
||||||
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Integer);
|
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Integer);
|
||||||
ASSERT_THAT(readStatement.fetchIntValue(0), -1);
|
ASSERT_THAT(readStatement.fetchIntValue(0), -1);
|
||||||
}
|
}
|
||||||
@@ -319,11 +321,11 @@ TEST_F(SqliteStatement, bind_invalid_long_long_id_to_null)
|
|||||||
TestLongLongId id;
|
TestLongLongId id;
|
||||||
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
|
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
|
||||||
|
|
||||||
statement.bind(1, id);
|
statement.bind(1, id, sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
|
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
|
||||||
readStatement.next();
|
readStatement.next(sourceLocation);
|
||||||
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Null);
|
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,11 +334,11 @@ TEST_F(SqliteStatement, bind_long_long_id)
|
|||||||
TestLongLongId id{TestLongLongId::create(42)};
|
TestLongLongId id{TestLongLongId::create(42)};
|
||||||
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
|
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
|
||||||
|
|
||||||
statement.bind(1, id);
|
statement.bind(1, id, sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
|
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
|
||||||
readStatement.next();
|
readStatement.next(sourceLocation);
|
||||||
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Integer);
|
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Integer);
|
||||||
ASSERT_THAT(readStatement.fetchIntValue(0), 42);
|
ASSERT_THAT(readStatement.fetchIntValue(0), 42);
|
||||||
}
|
}
|
||||||
@@ -345,8 +347,8 @@ TEST_F(SqliteStatement, bind_string)
|
|||||||
{
|
{
|
||||||
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE name=?", database);
|
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE name=?", database);
|
||||||
|
|
||||||
statement.bind(1, Utils::SmallStringView("foo"));
|
statement.bind(1, Utils::SmallStringView("foo"), sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
ASSERT_THAT(statement.fetchSmallStringViewValue(0), "foo");
|
ASSERT_THAT(statement.fetchSmallStringViewValue(0), "foo");
|
||||||
ASSERT_THAT(statement.fetchValue<double>(1), 23.3);
|
ASSERT_THAT(statement.fetchValue<double>(1), 23.3);
|
||||||
@@ -356,8 +358,8 @@ TEST_F(SqliteStatement, bind_integer)
|
|||||||
{
|
{
|
||||||
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=?", database);
|
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=?", database);
|
||||||
|
|
||||||
statement.bind(1, 40);
|
statement.bind(1, 40, sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
ASSERT_THAT(statement.fetchSmallStringViewValue(0), "poo");
|
ASSERT_THAT(statement.fetchSmallStringViewValue(0), "poo");
|
||||||
}
|
}
|
||||||
@@ -366,8 +368,8 @@ TEST_F(SqliteStatement, bind_long_integer)
|
|||||||
{
|
{
|
||||||
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=?", database);
|
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=?", database);
|
||||||
|
|
||||||
statement.bind(1, int64_t(40));
|
statement.bind(1, int64_t(40), sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
ASSERT_THAT(statement.fetchSmallStringViewValue(0), "poo");
|
ASSERT_THAT(statement.fetchSmallStringViewValue(0), "poo");
|
||||||
}
|
}
|
||||||
@@ -376,8 +378,8 @@ TEST_F(SqliteStatement, bind_double)
|
|||||||
{
|
{
|
||||||
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=?", database);
|
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=?", database);
|
||||||
|
|
||||||
statement.bind(1, 23.3);
|
statement.bind(1, 23.3, sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
ASSERT_THAT(statement.fetchSmallStringViewValue(0), "foo");
|
ASSERT_THAT(statement.fetchSmallStringViewValue(0), "foo");
|
||||||
}
|
}
|
||||||
@@ -387,8 +389,8 @@ TEST_F(SqliteStatement, bind_pointer)
|
|||||||
SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?, 5, 'int64')", database);
|
SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?, 5, 'int64')", database);
|
||||||
std::vector<long long> values{1, 1, 2, 3, 5};
|
std::vector<long long> values{1, 1, 2, 3, 5};
|
||||||
|
|
||||||
statement.bind(1, values.data());
|
statement.bind(1, values.data(), sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
ASSERT_THAT(statement.fetchIntValue(0), 1);
|
ASSERT_THAT(statement.fetchIntValue(0), 1);
|
||||||
}
|
}
|
||||||
@@ -398,11 +400,11 @@ TEST_F(SqliteStatement, bind_int_carray)
|
|||||||
SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database);
|
SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database);
|
||||||
std::vector<int> values{3, 10, 20, 33, 55};
|
std::vector<int> values{3, 10, 20, 33, 55};
|
||||||
|
|
||||||
statement.bind(1, values);
|
statement.bind(1, values, sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
ASSERT_THAT(statement.fetchIntValue(0), 33);
|
ASSERT_THAT(statement.fetchIntValue(0), 33);
|
||||||
}
|
}
|
||||||
@@ -412,11 +414,11 @@ TEST_F(SqliteStatement, bind_long_long_carray)
|
|||||||
SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database);
|
SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database);
|
||||||
std::vector<long long> values{3, 10, 20, 33, 55};
|
std::vector<long long> values{3, 10, 20, 33, 55};
|
||||||
|
|
||||||
statement.bind(1, values);
|
statement.bind(1, values, sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
ASSERT_THAT(statement.fetchLongLongValue(0), 33);
|
ASSERT_THAT(statement.fetchLongLongValue(0), 33);
|
||||||
}
|
}
|
||||||
@@ -426,11 +428,11 @@ TEST_F(SqliteStatement, bind_double_carray)
|
|||||||
SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database);
|
SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database);
|
||||||
std::vector<double> values{3.3, 10.2, 20.54, 33.21, 55};
|
std::vector<double> values{3.3, 10.2, 20.54, 33.21, 55};
|
||||||
|
|
||||||
statement.bind(1, values);
|
statement.bind(1, values, sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
ASSERT_THAT(statement.fetchDoubleValue(0), 33.21);
|
ASSERT_THAT(statement.fetchDoubleValue(0), 33.21);
|
||||||
}
|
}
|
||||||
@@ -440,11 +442,11 @@ TEST_F(SqliteStatement, bind_text_carray)
|
|||||||
SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database);
|
SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database);
|
||||||
std::vector<const char *> values{"yi", "er", "san", "se", "wu"};
|
std::vector<const char *> values{"yi", "er", "san", "se", "wu"};
|
||||||
|
|
||||||
statement.bind(1, values);
|
statement.bind(1, values, sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
ASSERT_THAT(statement.fetchSmallStringViewValue(0), Eq("se"));
|
ASSERT_THAT(statement.fetchSmallStringViewValue(0), Eq("se"));
|
||||||
}
|
}
|
||||||
@@ -456,8 +458,8 @@ TEST_F(SqliteStatement, bind_blob)
|
|||||||
auto bytePointer = reinterpret_cast<const std::byte *>(chars);
|
auto bytePointer = reinterpret_cast<const std::byte *>(chars);
|
||||||
Sqlite::BlobView bytes{bytePointer, sizeof(chars) - 1};
|
Sqlite::BlobView bytes{bytePointer, sizeof(chars) - 1};
|
||||||
|
|
||||||
statement.bind(1, bytes);
|
statement.bind(1, bytes, sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
ASSERT_THAT(statement.fetchBlobValue(0), Eq(bytes));
|
ASSERT_THAT(statement.fetchBlobValue(0), Eq(bytes));
|
||||||
}
|
}
|
||||||
@@ -467,8 +469,8 @@ TEST_F(SqliteStatement, bind_empty_blob)
|
|||||||
SqliteTestStatement<1, 1> statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database);
|
SqliteTestStatement<1, 1> statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database);
|
||||||
Sqlite::BlobView bytes;
|
Sqlite::BlobView bytes;
|
||||||
|
|
||||||
statement.bind(1, bytes);
|
statement.bind(1, bytes, sourceLocation);
|
||||||
statement.next();
|
statement.next(sourceLocation);
|
||||||
|
|
||||||
ASSERT_THAT(statement.fetchBlobValue(0), IsEmpty());
|
ASSERT_THAT(statement.fetchBlobValue(0), IsEmpty());
|
||||||
}
|
}
|
||||||
@@ -477,49 +479,51 @@ TEST_F(SqliteStatement, bind_index_is_zero_is_throwing_binding_index_is_out_of_b
|
|||||||
{
|
{
|
||||||
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
|
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
|
||||||
|
|
||||||
ASSERT_THROW(statement.bind(0, 40), Sqlite::BindingIndexIsOutOfRange);
|
ASSERT_THROW(statement.bind(0, 40, sourceLocation), Sqlite::BindingIndexIsOutOfRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteStatement, bind_index_is_zero_is_throwing_binding_index_is_out_of_bound_null)
|
TEST_F(SqliteStatement, bind_index_is_zero_is_throwing_binding_index_is_out_of_bound_null)
|
||||||
{
|
{
|
||||||
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
|
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
|
||||||
|
|
||||||
ASSERT_THROW(statement.bind(0, Sqlite::NullValue{}), Sqlite::BindingIndexIsOutOfRange);
|
ASSERT_THROW(statement.bind(0, Sqlite::NullValue{}, sourceLocation),
|
||||||
|
Sqlite::BindingIndexIsOutOfRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_long_long)
|
TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_long_long)
|
||||||
{
|
{
|
||||||
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
|
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
|
||||||
|
|
||||||
ASSERT_THROW(statement.bind(2, 40LL), Sqlite::BindingIndexIsOutOfRange);
|
ASSERT_THROW(statement.bind(2, 40LL, sourceLocation), Sqlite::BindingIndexIsOutOfRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_string_view)
|
TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_string_view)
|
||||||
{
|
{
|
||||||
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
|
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
|
||||||
|
|
||||||
ASSERT_THROW(statement.bind(2, "foo"), Sqlite::BindingIndexIsOutOfRange);
|
ASSERT_THROW(statement.bind(2, "foo", sourceLocation), Sqlite::BindingIndexIsOutOfRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_string_float)
|
TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_string_float)
|
||||||
{
|
{
|
||||||
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
|
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
|
||||||
|
|
||||||
ASSERT_THROW(statement.bind(2, 2.), Sqlite::BindingIndexIsOutOfRange);
|
ASSERT_THROW(statement.bind(2, 2., sourceLocation), Sqlite::BindingIndexIsOutOfRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_pointer)
|
TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_pointer)
|
||||||
{
|
{
|
||||||
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
|
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
|
||||||
|
|
||||||
ASSERT_THROW(statement.bind(2, nullptr), Sqlite::BindingIndexIsOutOfRange);
|
ASSERT_THROW(statement.bind(2, nullptr, sourceLocation), Sqlite::BindingIndexIsOutOfRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_value)
|
TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_value)
|
||||||
{
|
{
|
||||||
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
|
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
|
||||||
|
|
||||||
ASSERT_THROW(statement.bind(2, Sqlite::Value{1}), Sqlite::BindingIndexIsOutOfRange);
|
ASSERT_THROW(statement.bind(2, Sqlite::Value{1}, sourceLocation),
|
||||||
|
Sqlite::BindingIndexIsOutOfRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_blob)
|
TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_blob)
|
||||||
@@ -527,14 +531,14 @@ TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_
|
|||||||
SqliteTestStatement<1, 1> statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database);
|
SqliteTestStatement<1, 1> statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database);
|
||||||
Sqlite::BlobView bytes{QByteArray{"XXX"}};
|
Sqlite::BlobView bytes{QByteArray{"XXX"}};
|
||||||
|
|
||||||
ASSERT_THROW(statement.bind(2, bytes), Sqlite::BindingIndexIsOutOfRange);
|
ASSERT_THROW(statement.bind(2, bytes, sourceLocation), Sqlite::BindingIndexIsOutOfRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteStatement, bind_values)
|
TEST_F(SqliteStatement, bind_values)
|
||||||
{
|
{
|
||||||
SqliteTestStatement<0, 3> statement("UPDATE test SET name=?, number=? WHERE rowid=?", database);
|
SqliteTestStatement<0, 3> statement("UPDATE test SET name=?, number=? WHERE rowid=?", database);
|
||||||
|
|
||||||
statement.bindValues("see", 7.23, 1);
|
statement.bindValues(sourceLocation, "see", 7.23, 1);
|
||||||
statement.execute();
|
statement.execute();
|
||||||
|
|
||||||
ASSERT_THAT(statement, HasValues("see", "7.23", 1));
|
ASSERT_THAT(statement, HasValues("see", "7.23", 1));
|
||||||
@@ -544,7 +548,7 @@ TEST_F(SqliteStatement, bind_null_values)
|
|||||||
{
|
{
|
||||||
SqliteTestStatement<0, 3> statement("UPDATE test SET name=?, number=? WHERE rowid=?", database);
|
SqliteTestStatement<0, 3> statement("UPDATE test SET name=?, number=? WHERE rowid=?", database);
|
||||||
|
|
||||||
statement.bindValues(Sqlite::NullValue{}, Sqlite::Value{}, 1);
|
statement.bindValues(sourceLocation, Sqlite::NullValue{}, Sqlite::Value{}, 1);
|
||||||
statement.execute();
|
statement.execute();
|
||||||
|
|
||||||
ASSERT_THAT(statement, HasNullValues(1));
|
ASSERT_THAT(statement, HasNullValues(1));
|
||||||
@@ -1219,7 +1223,7 @@ TEST_F(SqliteStatement, get_optional_value_calls_reset)
|
|||||||
TEST_F(SqliteStatement, get_optional_value_calls_reset_if_exception_is_thrown)
|
TEST_F(SqliteStatement, get_optional_value_calls_reset_if_exception_is_thrown)
|
||||||
{
|
{
|
||||||
MockSqliteStatement<1, 1> mockStatement{databaseMock};
|
MockSqliteStatement<1, 1> mockStatement{databaseMock};
|
||||||
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
||||||
|
|
||||||
EXPECT_CALL(mockStatement, reset());
|
EXPECT_CALL(mockStatement, reset());
|
||||||
|
|
||||||
@@ -1355,7 +1359,7 @@ TEST_F(SqliteStatement, get_value_calls_reset_if_exception_is_thrown)
|
|||||||
int x = 0;
|
int x = 0;
|
||||||
};
|
};
|
||||||
MockSqliteStatement<1, 1> mockStatement{databaseMock};
|
MockSqliteStatement<1, 1> mockStatement{databaseMock};
|
||||||
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
||||||
|
|
||||||
EXPECT_CALL(mockStatement, reset());
|
EXPECT_CALL(mockStatement, reset());
|
||||||
|
|
||||||
@@ -1386,9 +1390,9 @@ TEST_F(SqliteStatement, get_range_with_transaction_without_arguments_calls)
|
|||||||
MockSqliteStatement<1, 0> mockStatement{databaseMock};
|
MockSqliteStatement<1, 0> mockStatement{databaseMock};
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, lock());
|
EXPECT_CALL(databaseMock, lock());
|
||||||
EXPECT_CALL(databaseMock, deferredBegin());
|
EXPECT_CALL(databaseMock, deferredBegin(_));
|
||||||
EXPECT_CALL(mockStatement, reset());
|
EXPECT_CALL(mockStatement, reset());
|
||||||
EXPECT_CALL(databaseMock, commit());
|
EXPECT_CALL(databaseMock, commit(_));
|
||||||
EXPECT_CALL(databaseMock, unlock());
|
EXPECT_CALL(databaseMock, unlock());
|
||||||
|
|
||||||
mockStatement.rangeWithTransaction<int>();
|
mockStatement.rangeWithTransaction<int>();
|
||||||
@@ -1397,7 +1401,7 @@ TEST_F(SqliteStatement, get_range_with_transaction_without_arguments_calls)
|
|||||||
TEST_F(SqliteStatement, get_values_without_arguments_calls_reset_if_exception_is_thrown)
|
TEST_F(SqliteStatement, get_values_without_arguments_calls_reset_if_exception_is_thrown)
|
||||||
{
|
{
|
||||||
MockSqliteStatement<1, 0> mockStatement{databaseMock};
|
MockSqliteStatement<1, 0> mockStatement{databaseMock};
|
||||||
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
||||||
|
|
||||||
EXPECT_CALL(mockStatement, reset());
|
EXPECT_CALL(mockStatement, reset());
|
||||||
|
|
||||||
@@ -1407,7 +1411,7 @@ TEST_F(SqliteStatement, get_values_without_arguments_calls_reset_if_exception_is
|
|||||||
TEST_F(SqliteStatement, get_range_without_arguments_calls_reset_if_exception_is_thrown)
|
TEST_F(SqliteStatement, get_range_without_arguments_calls_reset_if_exception_is_thrown)
|
||||||
{
|
{
|
||||||
MockSqliteStatement<1, 0> mockStatement{databaseMock};
|
MockSqliteStatement<1, 0> mockStatement{databaseMock};
|
||||||
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
||||||
auto range = mockStatement.range<int>();
|
auto range = mockStatement.range<int>();
|
||||||
|
|
||||||
EXPECT_CALL(mockStatement, reset());
|
EXPECT_CALL(mockStatement, reset());
|
||||||
@@ -1419,12 +1423,12 @@ TEST_F(SqliteStatement, get_range_with_transaction_without_arguments_calls_reset
|
|||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
MockSqliteStatement<1, 0> mockStatement{databaseMock};
|
MockSqliteStatement<1, 0> mockStatement{databaseMock};
|
||||||
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, lock());
|
EXPECT_CALL(databaseMock, lock());
|
||||||
EXPECT_CALL(databaseMock, deferredBegin());
|
EXPECT_CALL(databaseMock, deferredBegin(_));
|
||||||
EXPECT_CALL(mockStatement, reset());
|
EXPECT_CALL(mockStatement, reset());
|
||||||
EXPECT_CALL(databaseMock, rollback());
|
EXPECT_CALL(databaseMock, rollback(_));
|
||||||
EXPECT_CALL(databaseMock, unlock());
|
EXPECT_CALL(databaseMock, unlock());
|
||||||
|
|
||||||
EXPECT_THROW(
|
EXPECT_THROW(
|
||||||
@@ -1447,7 +1451,7 @@ TEST_F(SqliteStatement, get_values_with_simple_arguments_calls_reset)
|
|||||||
TEST_F(SqliteStatement, get_values_with_simple_arguments_calls_reset_if_exception_is_thrown)
|
TEST_F(SqliteStatement, get_values_with_simple_arguments_calls_reset_if_exception_is_thrown)
|
||||||
{
|
{
|
||||||
MockSqliteStatement<1, 2> mockStatement{databaseMock};
|
MockSqliteStatement<1, 2> mockStatement{databaseMock};
|
||||||
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
||||||
|
|
||||||
EXPECT_CALL(mockStatement, reset());
|
EXPECT_CALL(mockStatement, reset());
|
||||||
|
|
||||||
@@ -1458,7 +1462,7 @@ TEST_F(SqliteStatement, reset_if_write_is_throwing_exception)
|
|||||||
{
|
{
|
||||||
MockSqliteStatement<1, 1> mockStatement{databaseMock};
|
MockSqliteStatement<1, 1> mockStatement{databaseMock};
|
||||||
|
|
||||||
EXPECT_CALL(mockStatement, bind(1, TypedEq<Utils::SmallStringView>("bar")))
|
EXPECT_CALL(mockStatement, bind(1, TypedEq<Utils::SmallStringView>("bar"), _))
|
||||||
.WillOnce(Throw(Sqlite::StatementIsBusy("")));
|
.WillOnce(Throw(Sqlite::StatementIsBusy("")));
|
||||||
EXPECT_CALL(mockStatement, reset());
|
EXPECT_CALL(mockStatement, reset());
|
||||||
|
|
||||||
@@ -1469,7 +1473,7 @@ TEST_F(SqliteStatement, reset_if_execute_throws_exception)
|
|||||||
{
|
{
|
||||||
MockSqliteStatement<1, 0> mockStatement{databaseMock};
|
MockSqliteStatement<1, 0> mockStatement{databaseMock};
|
||||||
|
|
||||||
EXPECT_CALL(mockStatement, next()).WillOnce(Throw(Sqlite::StatementIsBusy("")));
|
EXPECT_CALL(mockStatement, next(_)).WillOnce(Throw(Sqlite::StatementIsBusy("")));
|
||||||
EXPECT_CALL(mockStatement, reset());
|
EXPECT_CALL(mockStatement, reset());
|
||||||
|
|
||||||
ASSERT_ANY_THROW(mockStatement.execute());
|
ASSERT_ANY_THROW(mockStatement.execute());
|
||||||
@@ -1576,7 +1580,7 @@ TEST_F(SqliteStatement, read_callback_throws_for_error)
|
|||||||
{
|
{
|
||||||
MockFunction<Sqlite::CallbackControl(Utils::SmallStringView, long long)> callbackMock;
|
MockFunction<Sqlite::CallbackControl(Utils::SmallStringView, long long)> callbackMock;
|
||||||
MockSqliteStatement<2> mockStatement{databaseMock};
|
MockSqliteStatement<2> mockStatement{databaseMock};
|
||||||
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
||||||
|
|
||||||
ASSERT_THROW(mockStatement.readCallback(callbackMock.AsStdFunction()), Sqlite::StatementHasError);
|
ASSERT_THROW(mockStatement.readCallback(callbackMock.AsStdFunction()), Sqlite::StatementHasError);
|
||||||
}
|
}
|
||||||
@@ -1585,7 +1589,7 @@ TEST_F(SqliteStatement, read_callback_calls_reset_if_exception_is_thrown)
|
|||||||
{
|
{
|
||||||
MockFunction<Sqlite::CallbackControl(Utils::SmallStringView, long long)> callbackMock;
|
MockFunction<Sqlite::CallbackControl(Utils::SmallStringView, long long)> callbackMock;
|
||||||
MockSqliteStatement<2> mockStatement{databaseMock};
|
MockSqliteStatement<2> mockStatement{databaseMock};
|
||||||
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
||||||
|
|
||||||
EXPECT_CALL(mockStatement, reset());
|
EXPECT_CALL(mockStatement, reset());
|
||||||
|
|
||||||
@@ -1626,7 +1630,7 @@ TEST_F(SqliteStatement, read_to_throws_for_error)
|
|||||||
{
|
{
|
||||||
std::deque<FooValue> values;
|
std::deque<FooValue> values;
|
||||||
MockSqliteStatement mockStatement{databaseMock};
|
MockSqliteStatement mockStatement{databaseMock};
|
||||||
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
||||||
|
|
||||||
ASSERT_THROW(mockStatement.readTo(values), Sqlite::StatementHasError);
|
ASSERT_THROW(mockStatement.readTo(values), Sqlite::StatementHasError);
|
||||||
}
|
}
|
||||||
@@ -1635,7 +1639,7 @@ TEST_F(SqliteStatement, read_to_calls_reset_if_exception_is_thrown)
|
|||||||
{
|
{
|
||||||
std::deque<FooValue> values;
|
std::deque<FooValue> values;
|
||||||
MockSqliteStatement mockStatement{databaseMock};
|
MockSqliteStatement mockStatement{databaseMock};
|
||||||
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
||||||
|
|
||||||
EXPECT_CALL(mockStatement, reset());
|
EXPECT_CALL(mockStatement, reset());
|
||||||
|
|
||||||
|
@@ -74,9 +74,9 @@ TEST_F(SqliteTable, initialize_table)
|
|||||||
table.addColumn("name");
|
table.addColumn("name");
|
||||||
table.addColumn("value");
|
table.addColumn("value");
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock,
|
EXPECT_CALL(
|
||||||
execute(Eq(
|
databaseMock,
|
||||||
"CREATE TEMPORARY TABLE IF NOT EXISTS testTable(name, value) WITHOUT ROWID")));
|
execute(Eq("CREATE TEMPORARY TABLE IF NOT EXISTS testTable(name, value) WITHOUT ROWID"), _));
|
||||||
|
|
||||||
table.initialize(databaseMock);
|
table.initialize(databaseMock);
|
||||||
}
|
}
|
||||||
@@ -90,13 +90,14 @@ TEST_F(SqliteTable, initialize_table_with_index)
|
|||||||
table.addIndex({column});
|
table.addIndex({column});
|
||||||
table.addIndex({column2}, "value IS NOT NULL");
|
table.addIndex({column2}, "value IS NOT NULL");
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name, value)")));
|
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name, value)"), _));
|
||||||
EXPECT_CALL(databaseMock,
|
EXPECT_CALL(
|
||||||
execute(Eq(
|
databaseMock,
|
||||||
"CREATE INDEX IF NOT EXISTS index_normal_testTable_name ON testTable(name)")));
|
execute(Eq("CREATE INDEX IF NOT EXISTS index_normal_testTable_name ON testTable(name)"), _));
|
||||||
EXPECT_CALL(databaseMock,
|
EXPECT_CALL(databaseMock,
|
||||||
execute(Eq("CREATE INDEX IF NOT EXISTS index_partial_testTable_value ON "
|
execute(Eq("CREATE INDEX IF NOT EXISTS index_partial_testTable_value ON "
|
||||||
"testTable(value) WHERE value IS NOT NULL")));
|
"testTable(value) WHERE value IS NOT NULL"),
|
||||||
|
_));
|
||||||
|
|
||||||
table.initialize(databaseMock);
|
table.initialize(databaseMock);
|
||||||
}
|
}
|
||||||
@@ -110,14 +111,15 @@ TEST_F(SqliteTable, initialize_table_with_unique_index)
|
|||||||
table.addUniqueIndex({column});
|
table.addUniqueIndex({column});
|
||||||
table.addUniqueIndex({column2}, "value IS NOT NULL");
|
table.addUniqueIndex({column2}, "value IS NOT NULL");
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name, value)")));
|
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name, value)"), _));
|
||||||
EXPECT_CALL(
|
EXPECT_CALL(
|
||||||
databaseMock,
|
databaseMock,
|
||||||
execute(Eq(
|
execute(
|
||||||
"CREATE UNIQUE INDEX IF NOT EXISTS index_unique_testTable_name ON testTable(name)")));
|
Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_unique_testTable_name ON testTable(name)"), _));
|
||||||
EXPECT_CALL(databaseMock,
|
EXPECT_CALL(databaseMock,
|
||||||
execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_unique_partial_testTable_value "
|
execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_unique_partial_testTable_value "
|
||||||
"ON testTable(value) WHERE value IS NOT NULL")));
|
"ON testTable(value) WHERE value IS NOT NULL"),
|
||||||
|
_));
|
||||||
|
|
||||||
table.initialize(databaseMock);
|
table.initialize(databaseMock);
|
||||||
}
|
}
|
||||||
@@ -135,7 +137,8 @@ TEST_F(SqliteTable, add_foreign_key_column_with_table_calls)
|
|||||||
|
|
||||||
EXPECT_CALL(databaseMock,
|
EXPECT_CALL(databaseMock,
|
||||||
execute(Eq("CREATE TABLE testTable(name INTEGER REFERENCES foreignTable ON UPDATE "
|
execute(Eq("CREATE TABLE testTable(name INTEGER REFERENCES foreignTable ON UPDATE "
|
||||||
"SET NULL ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)")));
|
"SET NULL ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)"),
|
||||||
|
_));
|
||||||
|
|
||||||
table.initialize(databaseMock);
|
table.initialize(databaseMock);
|
||||||
}
|
}
|
||||||
@@ -156,7 +159,8 @@ TEST_F(SqliteTable, add_foreign_key_column_with_column_calls)
|
|||||||
databaseMock,
|
databaseMock,
|
||||||
execute(
|
execute(
|
||||||
Eq("CREATE TABLE testTable(name TEXT REFERENCES foreignTable(foreignColumn) ON UPDATE "
|
Eq("CREATE TABLE testTable(name TEXT REFERENCES foreignTable(foreignColumn) ON UPDATE "
|
||||||
"SET DEFAULT ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED)")));
|
"SET DEFAULT ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED)"),
|
||||||
|
_));
|
||||||
|
|
||||||
table.initialize(databaseMock);
|
table.initialize(databaseMock);
|
||||||
}
|
}
|
||||||
@@ -307,7 +311,8 @@ TEST_F(SqliteTable, add_primary_table_contraint)
|
|||||||
const auto &nameColumn = table.addColumn("name");
|
const auto &nameColumn = table.addColumn("name");
|
||||||
table.addPrimaryKeyContraint({idColumn, nameColumn});
|
table.addPrimaryKeyContraint({idColumn, nameColumn});
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(id, name, PRIMARY KEY(id, name))")));
|
EXPECT_CALL(databaseMock,
|
||||||
|
execute(Eq("CREATE TABLE testTable(id, name, PRIMARY KEY(id, name))"), _));
|
||||||
|
|
||||||
table.initialize(databaseMock);
|
table.initialize(databaseMock);
|
||||||
}
|
}
|
||||||
@@ -367,7 +372,8 @@ TEST_F(StrictSqliteTable, initialize_table)
|
|||||||
|
|
||||||
EXPECT_CALL(databaseMock,
|
EXPECT_CALL(databaseMock,
|
||||||
execute(Eq("CREATE TEMPORARY TABLE IF NOT EXISTS testTable(name ANY, value ANY) "
|
execute(Eq("CREATE TEMPORARY TABLE IF NOT EXISTS testTable(name ANY, value ANY) "
|
||||||
"WITHOUT ROWID, STRICT")));
|
"WITHOUT ROWID, STRICT"),
|
||||||
|
_));
|
||||||
|
|
||||||
table.initialize(databaseMock);
|
table.initialize(databaseMock);
|
||||||
}
|
}
|
||||||
@@ -381,13 +387,14 @@ TEST_F(StrictSqliteTable, initialize_table_with_index)
|
|||||||
table.addIndex({column});
|
table.addIndex({column});
|
||||||
table.addIndex({column2}, "value IS NOT NULL");
|
table.addIndex({column2}, "value IS NOT NULL");
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name ANY, value ANY) STRICT")));
|
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name ANY, value ANY) STRICT"), _));
|
||||||
EXPECT_CALL(databaseMock,
|
EXPECT_CALL(
|
||||||
execute(Eq(
|
databaseMock,
|
||||||
"CREATE INDEX IF NOT EXISTS index_normal_testTable_name ON testTable(name)")));
|
execute(Eq("CREATE INDEX IF NOT EXISTS index_normal_testTable_name ON testTable(name)"), _));
|
||||||
EXPECT_CALL(databaseMock,
|
EXPECT_CALL(databaseMock,
|
||||||
execute(Eq("CREATE INDEX IF NOT EXISTS index_partial_testTable_value ON "
|
execute(Eq("CREATE INDEX IF NOT EXISTS index_partial_testTable_value ON "
|
||||||
"testTable(value) WHERE value IS NOT NULL")));
|
"testTable(value) WHERE value IS NOT NULL"),
|
||||||
|
_));
|
||||||
|
|
||||||
table.initialize(databaseMock);
|
table.initialize(databaseMock);
|
||||||
}
|
}
|
||||||
@@ -401,14 +408,15 @@ TEST_F(StrictSqliteTable, initialize_table_with_unique_index)
|
|||||||
table.addUniqueIndex({column});
|
table.addUniqueIndex({column});
|
||||||
table.addUniqueIndex({column2}, "value IS NOT NULL");
|
table.addUniqueIndex({column2}, "value IS NOT NULL");
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name ANY, value ANY) STRICT")));
|
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name ANY, value ANY) STRICT"), _));
|
||||||
EXPECT_CALL(
|
EXPECT_CALL(
|
||||||
databaseMock,
|
databaseMock,
|
||||||
execute(Eq(
|
execute(
|
||||||
"CREATE UNIQUE INDEX IF NOT EXISTS index_unique_testTable_name ON testTable(name)")));
|
Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_unique_testTable_name ON testTable(name)"), _));
|
||||||
EXPECT_CALL(databaseMock,
|
EXPECT_CALL(databaseMock,
|
||||||
execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_unique_partial_testTable_value "
|
execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_unique_partial_testTable_value "
|
||||||
"ON testTable(value) WHERE value IS NOT NULL")));
|
"ON testTable(value) WHERE value IS NOT NULL"),
|
||||||
|
_));
|
||||||
|
|
||||||
table.initialize(databaseMock);
|
table.initialize(databaseMock);
|
||||||
}
|
}
|
||||||
@@ -426,7 +434,8 @@ TEST_F(StrictSqliteTable, add_foreign_key_column_with_table_calls)
|
|||||||
|
|
||||||
EXPECT_CALL(databaseMock,
|
EXPECT_CALL(databaseMock,
|
||||||
execute(Eq("CREATE TABLE testTable(name INTEGER REFERENCES foreignTable ON UPDATE "
|
execute(Eq("CREATE TABLE testTable(name INTEGER REFERENCES foreignTable ON UPDATE "
|
||||||
"SET NULL ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED) STRICT")));
|
"SET NULL ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED) STRICT"),
|
||||||
|
_));
|
||||||
|
|
||||||
table.initialize(databaseMock);
|
table.initialize(databaseMock);
|
||||||
}
|
}
|
||||||
@@ -449,7 +458,8 @@ TEST_F(StrictSqliteTable, add_foreign_key_column_with_column_calls)
|
|||||||
databaseMock,
|
databaseMock,
|
||||||
execute(
|
execute(
|
||||||
Eq("CREATE TABLE testTable(name TEXT REFERENCES foreignTable(foreignColumn) ON UPDATE "
|
Eq("CREATE TABLE testTable(name TEXT REFERENCES foreignTable(foreignColumn) ON UPDATE "
|
||||||
"SET DEFAULT ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED) STRICT")));
|
"SET DEFAULT ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED) STRICT"),
|
||||||
|
_));
|
||||||
|
|
||||||
table.initialize(databaseMock);
|
table.initialize(databaseMock);
|
||||||
}
|
}
|
||||||
@@ -604,9 +614,9 @@ TEST_F(StrictSqliteTable, add_primary_table_contraint)
|
|||||||
const auto &nameColumn = table.addColumn("name");
|
const auto &nameColumn = table.addColumn("name");
|
||||||
table.addPrimaryKeyContraint({idColumn, nameColumn});
|
table.addPrimaryKeyContraint({idColumn, nameColumn});
|
||||||
|
|
||||||
EXPECT_CALL(databaseMock,
|
EXPECT_CALL(
|
||||||
execute(
|
databaseMock,
|
||||||
Eq("CREATE TABLE testTable(id ANY, name ANY, PRIMARY KEY(id, name)) STRICT")));
|
execute(Eq("CREATE TABLE testTable(id ANY, name ANY, PRIMARY KEY(id, name)) STRICT"), _));
|
||||||
|
|
||||||
table.initialize(databaseMock);
|
table.initialize(databaseMock);
|
||||||
}
|
}
|
||||||
|
@@ -4,15 +4,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <sqlitebasestatement.h>
|
#include <sqlitebasestatement.h>
|
||||||
|
|
||||||
template<int ResultCount, int BindParameterCount = 0>
|
template<int ResultCount, int BindParameterCount = 0>
|
||||||
class SqliteTestStatement
|
class SqliteTestStatement
|
||||||
: public Sqlite::StatementImplementation<Sqlite::BaseStatement, ResultCount, BindParameterCount>
|
: public Sqlite::StatementImplementation<Sqlite::BaseStatement, ResultCount, BindParameterCount>
|
||||||
{
|
{
|
||||||
using Base = Sqlite::StatementImplementation<Sqlite::BaseStatement, ResultCount, BindParameterCount>;
|
using Base = Sqlite::StatementImplementation<Sqlite::BaseStatement, ResultCount, BindParameterCount>;
|
||||||
|
|
||||||
|
static constexpr auto sourceLocation = Sqlite::source_location::current();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SqliteTestStatement(Utils::SmallStringView sqlStatement, Sqlite::Database &database)
|
explicit SqliteTestStatement(Utils::SmallStringView sqlStatement, Sqlite::Database &database)
|
||||||
: Base(sqlStatement, database)
|
: Base(sqlStatement, database, sourceLocation)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -35,8 +35,8 @@ TEST_F(SqliteTransaction, deferred_transaction_commit)
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, deferredBegin());
|
EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, commit());
|
EXPECT_CALL(mockTransactionBackend, commit(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
DeferredTransaction transaction{mockTransactionBackend};
|
DeferredTransaction transaction{mockTransactionBackend};
|
||||||
@@ -48,8 +48,8 @@ TEST_F(SqliteTransaction, deferred_transaction_roll_back)
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, deferredBegin());
|
EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, rollback());
|
EXPECT_CALL(mockTransactionBackend, rollback(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
DeferredTransaction transaction{mockTransactionBackend};
|
DeferredTransaction transaction{mockTransactionBackend};
|
||||||
@@ -60,8 +60,8 @@ TEST_F(SqliteTransaction, immediate_transaction_commit)
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, immediateBegin());
|
EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, commit());
|
EXPECT_CALL(mockTransactionBackend, commit(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
ImmediateTransaction transaction{mockTransactionBackend};
|
ImmediateTransaction transaction{mockTransactionBackend};
|
||||||
@@ -73,8 +73,8 @@ TEST_F(SqliteTransaction, immediate_transaction_roll_back)
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, immediateBegin());
|
EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, rollback());
|
EXPECT_CALL(mockTransactionBackend, rollback(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
ImmediateTransaction transaction{mockTransactionBackend};
|
ImmediateTransaction transaction{mockTransactionBackend};
|
||||||
@@ -85,8 +85,8 @@ TEST_F(SqliteTransaction, exclusive_transaction_commit)
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, exclusiveBegin());
|
EXPECT_CALL(mockTransactionBackend, exclusiveBegin(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, commit());
|
EXPECT_CALL(mockTransactionBackend, commit(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
ExclusiveTransaction transaction{mockTransactionBackend};
|
ExclusiveTransaction transaction{mockTransactionBackend};
|
||||||
@@ -98,8 +98,8 @@ TEST_F(SqliteTransaction, exclusive_transaction_roll_back)
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, exclusiveBegin());
|
EXPECT_CALL(mockTransactionBackend, exclusiveBegin(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, rollback());
|
EXPECT_CALL(mockTransactionBackend, rollback(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
ExclusiveTransaction transaction{mockTransactionBackend};
|
ExclusiveTransaction transaction{mockTransactionBackend};
|
||||||
@@ -110,8 +110,8 @@ TEST_F(SqliteTransaction, deferred_non_throwing_destructor_transaction_commit)
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, deferredBegin());
|
EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, commit());
|
EXPECT_CALL(mockTransactionBackend, commit(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
DeferredNonThrowingDestructorTransaction transaction{mockTransactionBackend};
|
DeferredNonThrowingDestructorTransaction transaction{mockTransactionBackend};
|
||||||
@@ -123,8 +123,8 @@ TEST_F(SqliteTransaction, deferred_non_throwing_destructor_transaction_commit_ca
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, deferredBegin());
|
EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, commit());
|
EXPECT_CALL(mockTransactionBackend, commit(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
DeferredNonThrowingDestructorTransaction transaction{mockTransactionBackend};
|
DeferredNonThrowingDestructorTransaction transaction{mockTransactionBackend};
|
||||||
@@ -136,8 +136,8 @@ TEST_F(SqliteTransaction, deferred_non_throwing_destructor_transaction_roll_back
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, deferredBegin());
|
EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, rollback());
|
EXPECT_CALL(mockTransactionBackend, rollback(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
DeferredNonThrowingDestructorTransaction transaction{mockTransactionBackend};
|
DeferredNonThrowingDestructorTransaction transaction{mockTransactionBackend};
|
||||||
@@ -148,8 +148,8 @@ TEST_F(SqliteTransaction, immediate_non_throwing_destructor_transaction_commit)
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, immediateBegin());
|
EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, commit());
|
EXPECT_CALL(mockTransactionBackend, commit(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
ImmediateNonThrowingDestructorTransaction transaction{mockTransactionBackend};
|
ImmediateNonThrowingDestructorTransaction transaction{mockTransactionBackend};
|
||||||
@@ -161,8 +161,8 @@ TEST_F(SqliteTransaction, immediate_non_throwing_destructor_transaction_roll_bac
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, immediateBegin());
|
EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, rollback());
|
EXPECT_CALL(mockTransactionBackend, rollback(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
ImmediateNonThrowingDestructorTransaction transaction{mockTransactionBackend};
|
ImmediateNonThrowingDestructorTransaction transaction{mockTransactionBackend};
|
||||||
@@ -173,8 +173,8 @@ TEST_F(SqliteTransaction, exclusive_non_throwing_destructor_transaction_commit)
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, exclusiveBegin());
|
EXPECT_CALL(mockTransactionBackend, exclusiveBegin(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, commit());
|
EXPECT_CALL(mockTransactionBackend, commit(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
ExclusiveNonThrowingDestructorTransaction transaction{mockTransactionBackend};
|
ExclusiveNonThrowingDestructorTransaction transaction{mockTransactionBackend};
|
||||||
@@ -186,8 +186,8 @@ TEST_F(SqliteTransaction, exclusive_t_non_throwing_destructorransaction_roll_bac
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, exclusiveBegin());
|
EXPECT_CALL(mockTransactionBackend, exclusiveBegin(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, rollback());
|
EXPECT_CALL(mockTransactionBackend, rollback(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
ExclusiveNonThrowingDestructorTransaction transaction{mockTransactionBackend};
|
ExclusiveNonThrowingDestructorTransaction transaction{mockTransactionBackend};
|
||||||
@@ -195,21 +195,21 @@ TEST_F(SqliteTransaction, exclusive_t_non_throwing_destructorransaction_roll_bac
|
|||||||
|
|
||||||
TEST_F(SqliteTransaction, deferred_transaction_begin_throws)
|
TEST_F(SqliteTransaction, deferred_transaction_begin_throws)
|
||||||
{
|
{
|
||||||
ON_CALL(mockTransactionBackend, deferredBegin()).WillByDefault(Throw(Sqlite::Exception()));
|
ON_CALL(mockTransactionBackend, deferredBegin(_)).WillByDefault(Throw(Sqlite::Exception()));
|
||||||
|
|
||||||
ASSERT_THROW(DeferredTransaction{mockTransactionBackend}, Sqlite::Exception);
|
ASSERT_THROW(DeferredTransaction{mockTransactionBackend}, Sqlite::Exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteTransaction, immediate_transaction_begin_throws)
|
TEST_F(SqliteTransaction, immediate_transaction_begin_throws)
|
||||||
{
|
{
|
||||||
ON_CALL(mockTransactionBackend, immediateBegin()).WillByDefault(Throw(Sqlite::Exception()));
|
ON_CALL(mockTransactionBackend, immediateBegin(_)).WillByDefault(Throw(Sqlite::Exception()));
|
||||||
|
|
||||||
ASSERT_THROW(ImmediateTransaction{mockTransactionBackend}, Sqlite::Exception);
|
ASSERT_THROW(ImmediateTransaction{mockTransactionBackend}, Sqlite::Exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteTransaction, exclusive_transaction_begin_throws)
|
TEST_F(SqliteTransaction, exclusive_transaction_begin_throws)
|
||||||
{
|
{
|
||||||
ON_CALL(mockTransactionBackend, exclusiveBegin()).WillByDefault(Throw(Sqlite::Exception()));
|
ON_CALL(mockTransactionBackend, exclusiveBegin(_)).WillByDefault(Throw(Sqlite::Exception()));
|
||||||
|
|
||||||
ASSERT_THROW(ExclusiveTransaction{mockTransactionBackend}, Sqlite::Exception);
|
ASSERT_THROW(ExclusiveTransaction{mockTransactionBackend}, Sqlite::Exception);
|
||||||
}
|
}
|
||||||
@@ -219,8 +219,8 @@ TEST_F(SqliteTransaction, deferred_transaction_begin_throws_and_not_rollback)
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, deferredBegin()).WillOnce(Throw(Sqlite::Exception()));
|
EXPECT_CALL(mockTransactionBackend, deferredBegin(_)).WillOnce(Throw(Sqlite::Exception()));
|
||||||
EXPECT_CALL(mockTransactionBackend, rollback()).Times(0);
|
EXPECT_CALL(mockTransactionBackend, rollback(_)).Times(0);
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
ASSERT_ANY_THROW(DeferredTransaction{mockTransactionBackend});
|
ASSERT_ANY_THROW(DeferredTransaction{mockTransactionBackend});
|
||||||
@@ -231,8 +231,8 @@ TEST_F(SqliteTransaction, immediate_transaction_begin_throws_and_not_rollback)
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, immediateBegin()).WillOnce(Throw(Sqlite::Exception()));
|
EXPECT_CALL(mockTransactionBackend, immediateBegin(_)).WillOnce(Throw(Sqlite::Exception()));
|
||||||
EXPECT_CALL(mockTransactionBackend, rollback()).Times(0);
|
EXPECT_CALL(mockTransactionBackend, rollback(_)).Times(0);
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
ASSERT_ANY_THROW(ImmediateTransaction{mockTransactionBackend});
|
ASSERT_ANY_THROW(ImmediateTransaction{mockTransactionBackend});
|
||||||
@@ -243,8 +243,8 @@ TEST_F(SqliteTransaction, exclusive_transaction_begin_throws_and_not_rollback)
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, exclusiveBegin()).WillOnce(Throw(Sqlite::Exception()));
|
EXPECT_CALL(mockTransactionBackend, exclusiveBegin(_)).WillOnce(Throw(Sqlite::Exception()));
|
||||||
EXPECT_CALL(mockTransactionBackend, rollback()).Times(0);
|
EXPECT_CALL(mockTransactionBackend, rollback(_)).Times(0);
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
ASSERT_ANY_THROW(ExclusiveTransaction{mockTransactionBackend});
|
ASSERT_ANY_THROW(ExclusiveTransaction{mockTransactionBackend});
|
||||||
@@ -252,7 +252,7 @@ TEST_F(SqliteTransaction, exclusive_transaction_begin_throws_and_not_rollback)
|
|||||||
|
|
||||||
TEST_F(SqliteTransaction, transaction_commit_throws)
|
TEST_F(SqliteTransaction, transaction_commit_throws)
|
||||||
{
|
{
|
||||||
ON_CALL(mockTransactionBackend, commit()).WillByDefault(Throw(Sqlite::Exception()));
|
ON_CALL(mockTransactionBackend, commit(_)).WillByDefault(Throw(Sqlite::Exception()));
|
||||||
ImmediateTransaction transaction{mockTransactionBackend};
|
ImmediateTransaction transaction{mockTransactionBackend};
|
||||||
|
|
||||||
ASSERT_THROW(transaction.commit(), Sqlite::Exception);
|
ASSERT_THROW(transaction.commit(), Sqlite::Exception);
|
||||||
@@ -260,14 +260,14 @@ TEST_F(SqliteTransaction, transaction_commit_throws)
|
|||||||
|
|
||||||
TEST_F(SqliteTransaction, transaction_rollback_in_destructor_throws)
|
TEST_F(SqliteTransaction, transaction_rollback_in_destructor_throws)
|
||||||
{
|
{
|
||||||
ON_CALL(mockTransactionBackend, rollback()).WillByDefault(Throw(Sqlite::Exception()));
|
ON_CALL(mockTransactionBackend, rollback(_)).WillByDefault(Throw(Sqlite::Exception()));
|
||||||
|
|
||||||
ASSERT_THROW(ExclusiveTransaction{mockTransactionBackend}, Sqlite::Exception);
|
ASSERT_THROW(ExclusiveTransaction{mockTransactionBackend}, Sqlite::Exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteTransaction, transaction_rollback_in_destructor_dont_throws)
|
TEST_F(SqliteTransaction, transaction_rollback_in_destructor_dont_throws)
|
||||||
{
|
{
|
||||||
ON_CALL(mockTransactionBackend, rollback()).WillByDefault(Throw(Sqlite::Exception()));
|
ON_CALL(mockTransactionBackend, rollback(_)).WillByDefault(Throw(Sqlite::Exception()));
|
||||||
|
|
||||||
ASSERT_NO_THROW(ExclusiveNonThrowingDestructorTransaction{mockTransactionBackend});
|
ASSERT_NO_THROW(ExclusiveNonThrowingDestructorTransaction{mockTransactionBackend});
|
||||||
}
|
}
|
||||||
@@ -277,8 +277,8 @@ TEST_F(SqliteTransaction, immediate_session_transaction_commit)
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, immediateSessionBegin());
|
EXPECT_CALL(mockTransactionBackend, immediateSessionBegin(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, sessionCommit());
|
EXPECT_CALL(mockTransactionBackend, sessionCommit(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
ImmediateSessionTransaction transaction{mockTransactionBackend};
|
ImmediateSessionTransaction transaction{mockTransactionBackend};
|
||||||
@@ -290,8 +290,8 @@ TEST_F(SqliteTransaction, immediate_session_transaction_roll_back)
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, immediateSessionBegin());
|
EXPECT_CALL(mockTransactionBackend, immediateSessionBegin(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, sessionRollback());
|
EXPECT_CALL(mockTransactionBackend, sessionRollback(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
ImmediateSessionTransaction transaction{mockTransactionBackend};
|
ImmediateSessionTransaction transaction{mockTransactionBackend};
|
||||||
@@ -299,14 +299,14 @@ TEST_F(SqliteTransaction, immediate_session_transaction_roll_back)
|
|||||||
|
|
||||||
TEST_F(SqliteTransaction, session_transaction_rollback_in_destructor_throws)
|
TEST_F(SqliteTransaction, session_transaction_rollback_in_destructor_throws)
|
||||||
{
|
{
|
||||||
ON_CALL(mockTransactionBackend, sessionRollback()).WillByDefault(Throw(Sqlite::Exception()));
|
ON_CALL(mockTransactionBackend, sessionRollback(_)).WillByDefault(Throw(Sqlite::Exception()));
|
||||||
|
|
||||||
ASSERT_THROW(ImmediateSessionTransaction{mockTransactionBackend}, Sqlite::Exception);
|
ASSERT_THROW(ImmediateSessionTransaction{mockTransactionBackend}, Sqlite::Exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SqliteTransaction, immidiate_session_transaction_begin_throws)
|
TEST_F(SqliteTransaction, immidiate_session_transaction_begin_throws)
|
||||||
{
|
{
|
||||||
ON_CALL(mockTransactionBackend, immediateSessionBegin()).WillByDefault(Throw(Sqlite::Exception()));
|
ON_CALL(mockTransactionBackend, immediateSessionBegin(_)).WillByDefault(Throw(Sqlite::Exception()));
|
||||||
|
|
||||||
ASSERT_THROW(ImmediateSessionTransaction{mockTransactionBackend}, Sqlite::Exception);
|
ASSERT_THROW(ImmediateSessionTransaction{mockTransactionBackend}, Sqlite::Exception);
|
||||||
}
|
}
|
||||||
@@ -316,8 +316,8 @@ TEST_F(SqliteTransaction, immediate_session_transaction_begin_throws_and_not_rol
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, immediateSessionBegin()).WillOnce(Throw(Sqlite::Exception()));
|
EXPECT_CALL(mockTransactionBackend, immediateSessionBegin(_)).WillOnce(Throw(Sqlite::Exception()));
|
||||||
EXPECT_CALL(mockTransactionBackend, sessionRollback()).Times(0);
|
EXPECT_CALL(mockTransactionBackend, sessionRollback(_)).Times(0);
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
ASSERT_ANY_THROW(ImmediateSessionTransaction{mockTransactionBackend});
|
ASSERT_ANY_THROW(ImmediateSessionTransaction{mockTransactionBackend});
|
||||||
@@ -328,9 +328,9 @@ TEST_F(SqliteTransaction, with_implicit_transaction_no_return_does_not_commit)
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, deferredBegin()).Times(0);
|
EXPECT_CALL(mockTransactionBackend, deferredBegin(_)).Times(0);
|
||||||
EXPECT_CALL(callableMock, Call());
|
EXPECT_CALL(callableMock, Call());
|
||||||
EXPECT_CALL(mockTransactionBackend, commit()).Times(0);
|
EXPECT_CALL(mockTransactionBackend, commit(_)).Times(0);
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
Sqlite::withImplicitTransaction(mockTransactionBackend, callableMock.AsStdFunction());
|
Sqlite::withImplicitTransaction(mockTransactionBackend, callableMock.AsStdFunction());
|
||||||
@@ -341,9 +341,9 @@ TEST_F(SqliteTransaction, with_implicit_transaction_with_return_does_not_commit)
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, deferredBegin()).Times(0);
|
EXPECT_CALL(mockTransactionBackend, deferredBegin(_)).Times(0);
|
||||||
EXPECT_CALL(callableWithReturnMock, Call());
|
EXPECT_CALL(callableWithReturnMock, Call());
|
||||||
EXPECT_CALL(mockTransactionBackend, commit()).Times(0);
|
EXPECT_CALL(mockTransactionBackend, commit(_)).Times(0);
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
Sqlite::withImplicitTransaction(mockTransactionBackend, callableWithReturnMock.AsStdFunction());
|
Sqlite::withImplicitTransaction(mockTransactionBackend, callableWithReturnMock.AsStdFunction());
|
||||||
@@ -365,9 +365,9 @@ TEST_F(SqliteTransaction, with_implicit_transaction_do_calls_rollsback_for_excep
|
|||||||
ON_CALL(callableMock, Call()).WillByDefault(Throw(std::exception{}));
|
ON_CALL(callableMock, Call()).WillByDefault(Throw(std::exception{}));
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, deferredBegin()).Times(0);
|
EXPECT_CALL(mockTransactionBackend, deferredBegin(_)).Times(0);
|
||||||
EXPECT_CALL(callableMock, Call());
|
EXPECT_CALL(callableMock, Call());
|
||||||
EXPECT_CALL(mockTransactionBackend, rollback()).Times(0);
|
EXPECT_CALL(mockTransactionBackend, rollback(_)).Times(0);
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -381,9 +381,9 @@ TEST_F(SqliteTransaction, with_deferred_transaction_no_return_commit)
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, deferredBegin());
|
EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
|
||||||
EXPECT_CALL(callableMock, Call());
|
EXPECT_CALL(callableMock, Call());
|
||||||
EXPECT_CALL(mockTransactionBackend, commit());
|
EXPECT_CALL(mockTransactionBackend, commit(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
Sqlite::withDeferredTransaction(mockTransactionBackend, callableMock.AsStdFunction());
|
Sqlite::withDeferredTransaction(mockTransactionBackend, callableMock.AsStdFunction());
|
||||||
@@ -394,9 +394,9 @@ TEST_F(SqliteTransaction, with_deferred_transaction_with_return_commit)
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, deferredBegin());
|
EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
|
||||||
EXPECT_CALL(callableWithReturnMock, Call());
|
EXPECT_CALL(callableWithReturnMock, Call());
|
||||||
EXPECT_CALL(mockTransactionBackend, commit());
|
EXPECT_CALL(mockTransactionBackend, commit(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
Sqlite::withDeferredTransaction(mockTransactionBackend, callableWithReturnMock.AsStdFunction());
|
Sqlite::withDeferredTransaction(mockTransactionBackend, callableWithReturnMock.AsStdFunction());
|
||||||
@@ -418,9 +418,9 @@ TEST_F(SqliteTransaction, with_deferred_transaction_rollsback_for_exception)
|
|||||||
ON_CALL(callableMock, Call()).WillByDefault(Throw(std::exception{}));
|
ON_CALL(callableMock, Call()).WillByDefault(Throw(std::exception{}));
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, deferredBegin());
|
EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
|
||||||
EXPECT_CALL(callableMock, Call());
|
EXPECT_CALL(callableMock, Call());
|
||||||
EXPECT_CALL(mockTransactionBackend, rollback());
|
EXPECT_CALL(mockTransactionBackend, rollback(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -434,9 +434,9 @@ TEST_F(SqliteTransaction, with_immediate_transaction_no_return_commit)
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, immediateBegin());
|
EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
|
||||||
EXPECT_CALL(callableMock, Call());
|
EXPECT_CALL(callableMock, Call());
|
||||||
EXPECT_CALL(mockTransactionBackend, commit());
|
EXPECT_CALL(mockTransactionBackend, commit(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
Sqlite::withImmediateTransaction(mockTransactionBackend, callableMock.AsStdFunction());
|
Sqlite::withImmediateTransaction(mockTransactionBackend, callableMock.AsStdFunction());
|
||||||
@@ -447,9 +447,9 @@ TEST_F(SqliteTransaction, with_immediate_transaction_with_return_commit)
|
|||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, immediateBegin());
|
EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
|
||||||
EXPECT_CALL(callableWithReturnMock, Call());
|
EXPECT_CALL(callableWithReturnMock, Call());
|
||||||
EXPECT_CALL(mockTransactionBackend, commit());
|
EXPECT_CALL(mockTransactionBackend, commit(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
Sqlite::withImmediateTransaction(mockTransactionBackend, callableWithReturnMock.AsStdFunction());
|
Sqlite::withImmediateTransaction(mockTransactionBackend, callableWithReturnMock.AsStdFunction());
|
||||||
@@ -471,9 +471,9 @@ TEST_F(SqliteTransaction, with_immediate_transaction_rollsback_for_exception)
|
|||||||
ON_CALL(callableMock, Call()).WillByDefault(Throw(std::exception{}));
|
ON_CALL(callableMock, Call()).WillByDefault(Throw(std::exception{}));
|
||||||
|
|
||||||
EXPECT_CALL(mockTransactionBackend, lock());
|
EXPECT_CALL(mockTransactionBackend, lock());
|
||||||
EXPECT_CALL(mockTransactionBackend, immediateBegin());
|
EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
|
||||||
EXPECT_CALL(callableMock, Call());
|
EXPECT_CALL(callableMock, Call());
|
||||||
EXPECT_CALL(mockTransactionBackend, rollback());
|
EXPECT_CALL(mockTransactionBackend, rollback(_));
|
||||||
EXPECT_CALL(mockTransactionBackend, unlock());
|
EXPECT_CALL(mockTransactionBackend, unlock());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
Reference in New Issue
Block a user