Sqlite: Extent Statement::values for other container

You can now use QList and QVarLenghtArray for values. The later is quite
interesting because it is not allocating for a provided capacity.

So you can now write:

statement.valuesWithTransaction<QVarLenghtArray<int, 1024>>();

And in almost all case no expensive memory is allocated. With the help
of NRVO there should be no copy too.

That is very useful for temporary values which are transformed into a
different type.

The capacity changed to an template parameter too:

statement.valuesWithTransaction<int, 1024>();

That is more clear than before:

statement.valuesWithTransaction<int>(1024);

Change-Id: I6d8d10ed9db0cc37f0579353a416e36e23c30415
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2023-08-27 16:16:23 +02:00
parent 9462c7a3e9
commit a55efac890
12 changed files with 114 additions and 74 deletions

View File

@@ -23,6 +23,7 @@
#include <optional> #include <optional>
#include <tuple> #include <tuple>
#include <type_traits> #include <type_traits>
#include <vector>
using std::int64_t; using std::int64_t;
@@ -172,12 +173,28 @@ public:
BaseStatement::next(); BaseStatement::next();
} }
template<typename ResultType, typename... QueryTypes> template<typename T>
auto values(std::size_t reserveSize, const QueryTypes &...queryValues) struct is_container : std::false_type
{};
template<typename... Args>
struct is_container<std::vector<Args...>> : std::true_type
{};
template<typename... Args>
struct is_container<QList<Args...>> : std::true_type
{};
template<typename T, qsizetype Prealloc>
struct is_container<QVarLengthArray<T, Prealloc>> : std::true_type
{};
template<typename Container,
std::size_t capacity = 32,
typename = std::enable_if_t<is_container<Container>::value>,
typename... QueryTypes>
auto values(const QueryTypes &...queryValues)
{ {
Resetter resetter{this}; Resetter resetter{this};
std::vector<ResultType> resultValues; Container resultValues;
resultValues.reserve(std::max(reserveSize, m_maximumResultCount)); resultValues.reserve(std::max(capacity, m_maximumResultCount));
bindValues(queryValues...); bindValues(queryValues...);
@@ -189,6 +206,16 @@ public:
return resultValues; return resultValues;
} }
template<typename ResultType,
std::size_t capacity = 32,
template<typename...> typename Container = std::vector,
typename = std::enable_if_t<!is_container<ResultType>::value>,
typename... QueryTypes>
auto values(const QueryTypes &...queryValues)
{
return values<Container<ResultType>, capacity>(queryValues...);
}
template<typename ResultType, typename... QueryTypes> template<typename ResultType, typename... QueryTypes>
auto value(const QueryTypes &...queryValues) auto value(const QueryTypes &...queryValues)
{ {

View File

@@ -47,11 +47,11 @@ public:
}); });
} }
template<typename ResultType, typename... QueryTypes> template<typename ResultType, std::size_t capacity = 32, typename... QueryTypes>
auto valuesWithTransaction(std::size_t reserveSize, const QueryTypes &...queryValues) auto valuesWithTransaction(const QueryTypes &...queryValues)
{ {
return withDeferredTransaction(Base::database(), [&] { return withDeferredTransaction(Base::database(), [&] {
return Base::template values<ResultType>(reserveSize, queryValues...); return Base::template values<ResultType, capacity>(queryValues...);
}); });
} }

View File

@@ -47,11 +47,13 @@ public:
}); });
} }
template<typename ResultType, typename... QueryTypes> template<typename ResultType,
auto valuesWithTransaction(std::size_t reserveSize, const QueryTypes &...queryValues) std::size_t capacity = 32,
typename... QueryTypes>
auto valuesWithTransaction(const QueryTypes &...queryValues)
{ {
return withImmediateTransaction(Base::database(), [&] { return withImmediateTransaction(Base::database(), [&] {
return Base::template values<ResultType>(reserveSize, queryValues...); return Base::template values<ResultType, capacity>(queryValues...);
}); });
} }

View File

@@ -110,7 +110,7 @@ void Sessions::revert()
" ORDER BY id DESC"}), " ORDER BY id DESC"}),
database}; database};
auto changeSets = selectChangeSets.values<SessionChangeSet>(1024); auto changeSets = selectChangeSets.values<SessionChangeSet, 1024>();
for (auto &changeSet : changeSets) { for (auto &changeSet : changeSets) {
int resultCode = sqlite3changeset_apply_v2(database.backend().sqliteDatabaseHandle(), int resultCode = sqlite3changeset_apply_v2(database.backend().sqliteDatabaseHandle(),
@@ -134,7 +134,7 @@ void Sessions::apply()
" ORDER BY id"}), " ORDER BY id"}),
database}; database};
auto changeSets = selectChangeSets.values<SessionChangeSet>(1024); auto changeSets = selectChangeSets.values<SessionChangeSet, 1024>();
for (auto &changeSet : changeSets) { for (auto &changeSet : changeSets) {
int resultCode = sqlite3changeset_apply_v2(database.backend().sqliteDatabaseHandle(), int resultCode = sqlite3changeset_apply_v2(database.backend().sqliteDatabaseHandle(),
@@ -170,7 +170,7 @@ SessionChangeSets Sessions::changeSets() const
" ORDER BY id DESC"}), " ORDER BY id DESC"}),
database}; database};
return selectChangeSets.values<SessionChangeSet>(1024); return selectChangeSets.values<SessionChangeSet, 1024>();
} }
void Sessions::Deleter::operator()(sqlite3_session *session) void Sessions::Deleter::operator()(sqlite3_session *session)

View File

@@ -160,14 +160,14 @@ public:
Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId) const override Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId) const override
{ {
return selectExportedTypesByTypeIdStatement return selectExportedTypesByTypeIdStatement
.template valuesWithTransaction<Storage::Info::ExportedTypeName>(4, typeId); .template valuesWithTransaction<Storage::Info::ExportedTypeName, 4>(typeId);
} }
Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId, Storage::Info::ExportedTypeNames exportedTypeNames(TypeId typeId,
SourceId sourceId) const override SourceId sourceId) const override
{ {
return selectExportedTypesByTypeIdAndSourceIdStatement return selectExportedTypesByTypeIdAndSourceIdStatement
.template valuesWithTransaction<Storage::Info::ExportedTypeName>(4, typeId, sourceId); .template valuesWithTransaction<Storage::Info::ExportedTypeName, 4>(typeId, sourceId);
} }
ImportId importId(const Storage::Import &import) const override ImportId importId(const Storage::Import &import) const override
@@ -197,16 +197,16 @@ public:
}); });
} }
PropertyDeclarationIds propertyDeclarationIds(TypeId typeId) const override QVarLengthArray<PropertyDeclarationId, 128> propertyDeclarationIds(TypeId typeId) const override
{ {
return selectPropertyDeclarationIdsForTypeStatement return selectPropertyDeclarationIdsForTypeStatement
.template valuesWithTransaction<PropertyDeclarationId>(32, typeId); .template valuesWithTransaction<QVarLengthArray<PropertyDeclarationId, 128>>(typeId);
} }
PropertyDeclarationIds localPropertyDeclarationIds(TypeId typeId) const override QVarLengthArray<PropertyDeclarationId, 128> localPropertyDeclarationIds(TypeId typeId) const override
{ {
return selectLocalPropertyDeclarationIdsForTypeStatement return selectLocalPropertyDeclarationIdsForTypeStatement
.template valuesWithTransaction<PropertyDeclarationId>(16, typeId); .template valuesWithTransaction<QVarLengthArray<PropertyDeclarationId, 128>>(typeId);
} }
PropertyDeclarationId propertyDeclarationId(TypeId typeId, PropertyDeclarationId propertyDeclarationId(TypeId typeId,
@@ -240,13 +240,13 @@ public:
std::vector<Utils::SmallString> signalDeclarationNames(TypeId typeId) const override std::vector<Utils::SmallString> signalDeclarationNames(TypeId typeId) const override
{ {
return selectSignalDeclarationNamesForTypeStatement return selectSignalDeclarationNamesForTypeStatement
.template valuesWithTransaction<Utils::SmallString>(32, typeId); .template valuesWithTransaction<Utils::SmallString, 32>(typeId);
} }
std::vector<Utils::SmallString> functionDeclarationNames(TypeId typeId) const override std::vector<Utils::SmallString> functionDeclarationNames(TypeId typeId) const override
{ {
return selectFuncionDeclarationNamesForTypeStatement return selectFuncionDeclarationNamesForTypeStatement
.template valuesWithTransaction<Utils::SmallString>(32, typeId); .template valuesWithTransaction<Utils::SmallString, 32>(typeId);
} }
std::optional<Utils::SmallString> propertyName(PropertyDeclarationId propertyDeclarationId) const override std::optional<Utils::SmallString> propertyName(PropertyDeclarationId propertyDeclarationId) const override
@@ -280,14 +280,14 @@ public:
TypeIds prototypeIds(TypeId type) const override TypeIds prototypeIds(TypeId type) const override
{ {
return selectPrototypeIdsForTypeIdInOrderStatement.template valuesWithTransaction<TypeId>(16, return selectPrototypeIdsForTypeIdInOrderStatement.template valuesWithTransaction<TypeId, 16>(
type); type);
} }
TypeIds prototypeAndSelfIds(TypeId type) const override TypeIds prototypeAndSelfIds(TypeId type) const override
{ {
return selectPrototypeAndSelfIdsForTypeIdInOrderStatement return selectPrototypeAndSelfIdsForTypeIdInOrderStatement
.template valuesWithTransaction<TypeId>(16, type); .template valuesWithTransaction<TypeId, 16>(type);
} }
template<typename... TypeIds> template<typename... TypeIds>
@@ -383,7 +383,7 @@ public:
Storage::Synchronization::Types fetchTypes() Storage::Synchronization::Types fetchTypes()
{ {
return Sqlite::withDeferredTransaction(database, [&] { return Sqlite::withDeferredTransaction(database, [&] {
auto types = selectTypesStatement.template values<Storage::Synchronization::Type>(64); auto types = selectTypesStatement.template values<Storage::Synchronization::Type, 64>();
for (Storage::Synchronization::Type &type : types) { for (Storage::Synchronization::Type &type : types) {
type.exportedTypes = fetchExportedTypes(type.typeId); type.exportedTypes = fetchExportedTypes(type.typeId);
@@ -441,8 +441,8 @@ public:
auto fetchAllSourceContexts() const auto fetchAllSourceContexts() const
{ {
return selectAllSourceContextsStatement.template valuesWithTransaction<Cache::SourceContext>( return selectAllSourceContextsStatement
128); .template valuesWithTransaction<Cache::SourceContext, 128>();
} }
SourceId fetchSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName) SourceId fetchSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName)
@@ -484,7 +484,7 @@ public:
auto fetchAllSources() const auto fetchAllSources() const
{ {
return selectAllSourcesStatement.template valuesWithTransaction<Cache::Source>(1024); return selectAllSourcesStatement.template valuesWithTransaction<Cache::Source, 1024>();
} }
SourceId fetchSourceIdUnguarded(SourceContextId sourceContextId, Utils::SmallStringView sourceName) SourceId fetchSourceIdUnguarded(SourceContextId sourceContextId, Utils::SmallStringView sourceName)
@@ -517,14 +517,15 @@ public:
Storage::Synchronization::ProjectDatas fetchProjectDatas(SourceId projectSourceId) const override Storage::Synchronization::ProjectDatas fetchProjectDatas(SourceId projectSourceId) const override
{ {
return selectProjectDatasForSourceIdStatement return selectProjectDatasForSourceIdStatement
.template valuesWithTransaction<Storage::Synchronization::ProjectData>(64, .template valuesWithTransaction<Storage::Synchronization::ProjectData, 1024>(
projectSourceId); projectSourceId);
} }
Storage::Synchronization::ProjectDatas fetchProjectDatas(const SourceIds &projectSourceIds) const Storage::Synchronization::ProjectDatas fetchProjectDatas(const SourceIds &projectSourceIds) const
{ {
return selectProjectDatasForSourceIdsStatement.template valuesWithTransaction< return selectProjectDatasForSourceIdsStatement
Storage::Synchronization::ProjectData>(64, toIntegers(projectSourceIds)); .template valuesWithTransaction<Storage::Synchronization::ProjectData, 64>(
toIntegers(projectSourceIds));
} }
void setPropertyEditorPathId(TypeId typeId, SourceId pathId) void setPropertyEditorPathId(TypeId typeId, SourceId pathId)
@@ -595,7 +596,7 @@ private:
auto fetchAllModules() const auto fetchAllModules() const
{ {
return selectAllModulesStatement.template valuesWithTransaction<Module>(128); return selectAllModulesStatement.template valuesWithTransaction<Module, 128>();
} }
class AliasPropertyDeclaration class AliasPropertyDeclaration
@@ -728,7 +729,7 @@ private:
TypeIds fetchTypeIds(const SourceIds &sourceIds) TypeIds fetchTypeIds(const SourceIds &sourceIds)
{ {
return selectTypeIdsForSourceIdsStatement.template values<TypeId>(128, toIntegers(sourceIds)); return selectTypeIdsForSourceIdsStatement.template values<TypeId, 128>(toIntegers(sourceIds));
} }
void unique(SourceIds &sourceIds) void unique(SourceIds &sourceIds)
@@ -2324,13 +2325,13 @@ private:
auto fetchExportedTypes(TypeId typeId) auto fetchExportedTypes(TypeId typeId)
{ {
return selectExportedTypesByTypeIdStatement return selectExportedTypesByTypeIdStatement
.template values<Storage::Synchronization::ExportedType>(12, typeId); .template values<Storage::Synchronization::ExportedType, 12>(typeId);
} }
auto fetchPropertyDeclarations(TypeId typeId) auto fetchPropertyDeclarations(TypeId typeId)
{ {
return selectPropertyDeclarationsByTypeIdStatement return selectPropertyDeclarationsByTypeIdStatement
.template values<Storage::Synchronization::PropertyDeclaration>(24, typeId); .template values<Storage::Synchronization::PropertyDeclaration, 24>(typeId);
} }
auto fetchFunctionDeclarations(TypeId typeId) auto fetchFunctionDeclarations(TypeId typeId)
@@ -2341,8 +2342,9 @@ private:
Utils::SmallStringView returnType, Utils::SmallStringView returnType,
FunctionDeclarationId functionDeclarationId) { FunctionDeclarationId functionDeclarationId) {
auto &functionDeclaration = functionDeclarations.emplace_back(name, returnType); auto &functionDeclaration = functionDeclarations.emplace_back(name, returnType);
functionDeclaration.parameters = selectFunctionParameterDeclarationsStatement.template values< functionDeclaration.parameters = selectFunctionParameterDeclarationsStatement
Storage::Synchronization::ParameterDeclaration>(8, functionDeclarationId); .template values<Storage::Synchronization::ParameterDeclaration,
8>(functionDeclarationId);
}; };
selectFunctionDeclarationsForTypeIdWithoutSignatureStatement.readCallback(callback, typeId); selectFunctionDeclarationsForTypeIdWithoutSignatureStatement.readCallback(callback, typeId);
@@ -2356,8 +2358,9 @@ private:
auto callback = [&](Utils::SmallStringView name, SignalDeclarationId signalDeclarationId) { auto callback = [&](Utils::SmallStringView name, SignalDeclarationId signalDeclarationId) {
auto &signalDeclaration = signalDeclarations.emplace_back(name); auto &signalDeclaration = signalDeclarations.emplace_back(name);
signalDeclaration.parameters = selectSignalParameterDeclarationsStatement.template values< signalDeclaration.parameters = selectSignalParameterDeclarationsStatement
Storage::Synchronization::ParameterDeclaration>(8, signalDeclarationId); .template values<Storage::Synchronization::ParameterDeclaration,
8>(signalDeclarationId);
}; };
selectSignalDeclarationsForTypeIdWithoutSignatureStatement.readCallback(callback, typeId); selectSignalDeclarationsForTypeIdWithoutSignatureStatement.readCallback(callback, typeId);
@@ -2373,8 +2376,9 @@ private:
EnumerationDeclarationId enumerationDeclarationId) { EnumerationDeclarationId enumerationDeclarationId) {
enumerationDeclarations.emplace_back( enumerationDeclarations.emplace_back(
name, name,
selectEnumeratorDeclarationStatement.template values< selectEnumeratorDeclarationStatement
Storage::Synchronization::EnumeratorDeclaration>(8, enumerationDeclarationId)); .template values<Storage::Synchronization::EnumeratorDeclaration, 8>(
enumerationDeclarationId));
}; };
selectEnumerationDeclarationsForTypeIdWithoutEnumeratorDeclarationsStatement selectEnumerationDeclarationsForTypeIdWithoutEnumeratorDeclarationsStatement

View File

@@ -10,6 +10,8 @@
#include <utils/smallstringview.h> #include <utils/smallstringview.h>
#include <QVarLengthArray>
namespace QmlDesigner { namespace QmlDesigner {
class ProjectStorageInterface class ProjectStorageInterface
@@ -42,8 +44,8 @@ public:
= 0; = 0;
virtual ImportedTypeNameId importedTypeNameId(SourceId sourceId, Utils::SmallStringView typeName) virtual ImportedTypeNameId importedTypeNameId(SourceId sourceId, Utils::SmallStringView typeName)
= 0; = 0;
virtual PropertyDeclarationIds propertyDeclarationIds(TypeId typeId) const = 0; virtual QVarLengthArray<PropertyDeclarationId, 128> propertyDeclarationIds(TypeId typeId) const = 0;
virtual PropertyDeclarationIds localPropertyDeclarationIds(TypeId typeId) const = 0; virtual QVarLengthArray<PropertyDeclarationId, 128> localPropertyDeclarationIds(TypeId typeId) const = 0;
virtual PropertyDeclarationId propertyDeclarationId(TypeId typeId, virtual PropertyDeclarationId propertyDeclarationId(TypeId typeId,
::Utils::SmallStringView propertyName) const ::Utils::SmallStringView propertyName) const
= 0; = 0;

View File

@@ -140,11 +140,11 @@ public:
(QmlDesigner::SourceId sourceId, ::Utils::SmallStringView typeName), (QmlDesigner::SourceId sourceId, ::Utils::SmallStringView typeName),
(override)); (override));
MOCK_METHOD(QmlDesigner::PropertyDeclarationIds, MOCK_METHOD((QVarLengthArray<QmlDesigner::PropertyDeclarationId, 128>),
propertyDeclarationIds, propertyDeclarationIds,
(QmlDesigner::TypeId typeId), (QmlDesigner::TypeId typeId),
(const, override)); (const, override));
MOCK_METHOD(QmlDesigner::PropertyDeclarationIds, MOCK_METHOD((QVarLengthArray<QmlDesigner::PropertyDeclarationId, 128>),
localPropertyDeclarationIds, localPropertyDeclarationIds,
(QmlDesigner::TypeId typeId), (QmlDesigner::TypeId typeId),
(const, override)); (const, override));

View File

@@ -234,11 +234,15 @@ private:
MATCHER(IsSorted, std::string(negation ? "isn't sorted" : "is sorted")) MATCHER(IsSorted, std::string(negation ? "isn't sorted" : "is sorted"))
{ {
using std::begin;
using std::end;
return std::is_sorted(begin(arg), end(arg)); return std::is_sorted(begin(arg), end(arg));
} }
MATCHER(StringsAreSorted, std::string(negation ? "isn't sorted" : "is sorted")) MATCHER(StringsAreSorted, std::string(negation ? "isn't sorted" : "is sorted"))
{ {
using std::begin;
using std::end;
return std::is_sorted(begin(arg), end(arg), [](const auto &first, const auto &second) { return std::is_sorted(begin(arg), end(arg), [](const auto &first, const auto &second) {
return Sqlite::compare(first, second) < 0; return Sqlite::compare(first, second) < 0;
}); });

View File

@@ -79,7 +79,7 @@ public:
auto select() { return selectViewsStatement.range<KeyValueView>(); } auto select() { return selectViewsStatement.range<KeyValueView>(); }
auto fetchKeyValues() { return selectValuesStatement.values<KeyValue>(24); } auto fetchKeyValues() { return selectValuesStatement.values<KeyValue>(); }
protected: protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};

View File

@@ -47,7 +47,7 @@ protected:
std::vector<Utils::SmallString> names() const std::vector<Utils::SmallString> names() const
{ {
return Sqlite::ReadStatement<1>("SELECT name FROM test", database).values<Utils::SmallString>(8); return Sqlite::ReadStatement<1>("SELECT name FROM test", database).values<Utils::SmallString>();
} }
static void updateHookCallback( static void updateHookCallback(

View File

@@ -102,8 +102,9 @@ class SqliteSessions : public testing::Test
protected: protected:
SqliteSessions() { sessions.setAttachedTables({"data", "tags"}); } SqliteSessions() { sessions.setAttachedTables({"data", "tags"}); }
std::vector<Data> fetchData() { return selectData.values<Data>(8); } std::vector<Data> fetchData() { return selectData.values<Data>(); }
std::vector<Tag> fetchTags() { return selectTags.values<Tag>(8); }
std::vector<Tag> fetchTags() { return selectTags.values<Tag>(); }
protected: protected:
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};

View File

@@ -519,7 +519,7 @@ TEST_F(SqliteStatement, write_pointer_values)
SqliteTestStatement<1, 2> statement("SELECT value FROM carray(?, ?, 'int64')", database); SqliteTestStatement<1, 2> statement("SELECT value FROM carray(?, ?, 'int64')", database);
std::vector<long long> values{1, 1, 2, 3, 5}; std::vector<long long> values{1, 1, 2, 3, 5};
auto results = statement.values<int>(5, values.data(), int(values.size())); auto results = statement.values<int, 5>(values.data(), int(values.size()));
ASSERT_THAT(results, ElementsAre(1, 1, 2, 3, 5)); ASSERT_THAT(results, ElementsAre(1, 1, 2, 3, 5));
} }
@@ -529,7 +529,7 @@ TEST_F(SqliteStatement, write_int_carray_values)
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};
auto results = statement.values<int>(5, Utils::span(values)); auto results = statement.values<int, 5>(Utils::span(values));
ASSERT_THAT(results, ElementsAre(3, 10, 20, 33, 55)); ASSERT_THAT(results, ElementsAre(3, 10, 20, 33, 55));
} }
@@ -539,7 +539,7 @@ TEST_F(SqliteStatement, write_long_long_carray_values)
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};
auto results = statement.values<long long>(5, Utils::span(values)); auto results = statement.values<long long, 5>(Utils::span(values));
ASSERT_THAT(results, ElementsAre(3, 10, 20, 33, 55)); ASSERT_THAT(results, ElementsAre(3, 10, 20, 33, 55));
} }
@@ -549,7 +549,7 @@ TEST_F(SqliteStatement, write_double_carray_values)
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};
auto results = statement.values<double>(5, Utils::span(values)); auto results = statement.values<double, 5>(Utils::span(values));
ASSERT_THAT(results, ElementsAre(3.3, 10.2, 20.54, 33.21, 55)); ASSERT_THAT(results, ElementsAre(3.3, 10.2, 20.54, 33.21, 55));
} }
@@ -559,7 +559,7 @@ TEST_F(SqliteStatement, write_text_carray_values)
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"};
auto results = statement.values<Utils::SmallString>(5, Utils::span(values)); auto results = statement.values<Utils::SmallString, 5>(Utils::span(values));
ASSERT_THAT(results, ElementsAre("yi", "er", "san", "se", "wu")); ASSERT_THAT(results, ElementsAre("yi", "er", "san", "se", "wu"));
} }
@@ -725,7 +725,7 @@ TEST_F(SqliteStatement, get_tuple_values_without_arguments)
using Tuple = std::tuple<Utils::SmallString, double, int>; using Tuple = std::tuple<Utils::SmallString, double, int>;
ReadStatement<3> statement("SELECT name, number, value FROM test", database); ReadStatement<3> statement("SELECT name, number, value FROM test", database);
auto values = statement.values<Tuple>(3); auto values = statement.values<Tuple>();
ASSERT_THAT(values, ASSERT_THAT(values,
UnorderedElementsAre(Tuple{"bar", 0, 1}, Tuple{"foo", 23.3, 2}, Tuple{"poo", 40.0, 3})); UnorderedElementsAre(Tuple{"bar", 0, 1}, Tuple{"foo", 23.3, 2}, Tuple{"poo", 40.0, 3}));
@@ -851,7 +851,7 @@ TEST_F(SqliteStatement, get_single_values_without_arguments)
{ {
ReadStatement<1> statement("SELECT name FROM test", database); ReadStatement<1> statement("SELECT name FROM test", database);
std::vector<Utils::SmallString> values = statement.values<Utils::SmallString>(3); std::vector<Utils::SmallString> values = statement.values<Utils::SmallString>();
ASSERT_THAT(values, UnorderedElementsAre("bar", "foo", "poo")); ASSERT_THAT(values, UnorderedElementsAre("bar", "foo", "poo"));
} }
@@ -901,7 +901,7 @@ TEST_F(SqliteStatement, get_single_sqlite_values_without_arguments)
ReadStatement<1> statement("SELECT number FROM test", database); ReadStatement<1> statement("SELECT number FROM test", database);
database.execute("INSERT INTO test VALUES (NULL, NULL, NULL)"); database.execute("INSERT INTO test VALUES (NULL, NULL, NULL)");
std::vector<FooValue> values = statement.values<FooValue>(3); std::vector<FooValue> values = statement.values<FooValue>();
ASSERT_THAT(values, UnorderedElementsAre(Eq("blah"), Eq(23.3), Eq(40), IsNull())); ASSERT_THAT(values, UnorderedElementsAre(Eq("blah"), Eq(23.3), Eq(40), IsNull()));
} }
@@ -933,7 +933,7 @@ TEST_F(SqliteStatement, get_struct_values_without_arguments)
{ {
ReadStatement<3> statement("SELECT name, number, value FROM test", database); ReadStatement<3> statement("SELECT name, number, value FROM test", database);
auto values = statement.values<Output>(3); auto values = statement.values<Output>();
ASSERT_THAT(values, ASSERT_THAT(values,
UnorderedElementsAre(Output{"bar", "blah", 1}, UnorderedElementsAre(Output{"bar", "blah", 1},
@@ -971,9 +971,9 @@ TEST_F(SqliteStatement, get_struct_range_with_transaction_without_arguments)
TEST_F(SqliteStatement, get_values_for_single_output_with_binding_multiple_times) TEST_F(SqliteStatement, get_values_for_single_output_with_binding_multiple_times)
{ {
ReadStatement<1, 1> statement("SELECT name FROM test WHERE number=?", database); ReadStatement<1, 1> statement("SELECT name FROM test WHERE number=?", database);
statement.values<Utils::SmallString>(3, 40); statement.values<Utils::SmallString, 3>(40);
std::vector<Utils::SmallString> values = statement.values<Utils::SmallString>(3, 40); std::vector<Utils::SmallString> values = statement.values<Utils::SmallString, 3>(40);
ASSERT_THAT(values, ElementsAre("poo")); ASSERT_THAT(values, ElementsAre("poo"));
} }
@@ -981,7 +981,7 @@ TEST_F(SqliteStatement, get_values_for_single_output_with_binding_multiple_times
TEST_F(SqliteStatement, get_range_for_single_output_with_binding_multiple_times) TEST_F(SqliteStatement, get_range_for_single_output_with_binding_multiple_times)
{ {
ReadStatement<1, 1> statement("SELECT name FROM test WHERE number=?", database); ReadStatement<1, 1> statement("SELECT name FROM test WHERE number=?", database);
statement.values<Utils::SmallString>(3, 40); statement.values<Utils::SmallString, 3>(40);
auto range = statement.range<Utils::SmallStringView>(40); auto range = statement.range<Utils::SmallStringView>(40);
std::vector<Utils::SmallString> values{range.begin(), range.end()}; std::vector<Utils::SmallString> values{range.begin(), range.end()};
@@ -992,7 +992,7 @@ TEST_F(SqliteStatement, get_range_for_single_output_with_binding_multiple_times)
TEST_F(SqliteStatement, get_range_with_transaction_for_single_output_with_binding_multiple_times) TEST_F(SqliteStatement, get_range_with_transaction_for_single_output_with_binding_multiple_times)
{ {
ReadStatement<1, 1> statement("SELECT name FROM test WHERE number=?", database); ReadStatement<1, 1> statement("SELECT name FROM test WHERE number=?", database);
statement.values<Utils::SmallString>(3, 40); statement.values<Utils::SmallString, 3>(40);
database.unlock(); database.unlock();
std::vector<Utils::SmallString> values = toValues( std::vector<Utils::SmallString> values = toValues(
@@ -1008,7 +1008,7 @@ TEST_F(SqliteStatement, get_values_for_multiple_output_values_and_multiple_query
ReadStatement<3, 3> statement( ReadStatement<3, 3> statement(
"SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database); "SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database);
auto values = statement.values<Tuple>(3, "bar", "blah", 1); auto values = statement.values<Tuple, 3>("bar", "blah", 1);
ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1})); ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1}));
} }
@@ -1043,9 +1043,9 @@ TEST_F(SqliteStatement, call_get_values_for_multiple_output_values_and_multiple_
using Tuple = std::tuple<Utils::SmallString, Utils::SmallString, long long>; using Tuple = std::tuple<Utils::SmallString, Utils::SmallString, long long>;
ReadStatement<3, 2> statement("SELECT name, number, value FROM test WHERE name=? AND number=?", ReadStatement<3, 2> statement("SELECT name, number, value FROM test WHERE name=? AND number=?",
database); database);
statement.values<Tuple>(3, "bar", "blah"); statement.values<Tuple, 3>("bar", "blah");
auto values = statement.values<Tuple>(3, "bar", "blah"); auto values = statement.values<Tuple, 3>("bar", "blah");
ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1})); ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1}));
} }
@@ -1086,7 +1086,7 @@ TEST_F(SqliteStatement, get_struct_output_values_and_multiple_query_value)
ReadStatement<3, 3> statement( ReadStatement<3, 3> statement(
"SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database); "SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database);
auto values = statement.values<Output>(3, "bar", "blah", 1); auto values = statement.values<Output, 3>("bar", "blah", 1);
ASSERT_THAT(values, ElementsAre(Output{"bar", "blah", 1})); ASSERT_THAT(values, ElementsAre(Output{"bar", "blah", 1}));
} }
@@ -1099,7 +1099,7 @@ TEST_F(SqliteStatement, get_blob_values)
auto bytePointer = reinterpret_cast<const std::byte *>(&value); auto bytePointer = reinterpret_cast<const std::byte *>(&value);
Sqlite::BlobView bytes{bytePointer, 4}; Sqlite::BlobView bytes{bytePointer, 4};
auto values = statement.values<Sqlite::Blob>(1); auto values = statement.values<Sqlite::Blob>();
ASSERT_THAT(values, ElementsAre(Field(&Sqlite::Blob::bytes, Eq(bytes)))); ASSERT_THAT(values, ElementsAre(Field(&Sqlite::Blob::bytes, Eq(bytes))));
} }
@@ -1299,7 +1299,7 @@ TEST_F(SqliteStatement, get_values_without_arguments_calls_reset)
EXPECT_CALL(mockStatement, reset()); EXPECT_CALL(mockStatement, reset());
mockStatement.values<int>(3); mockStatement.values<int>();
} }
TEST_F(SqliteStatement, get_range_without_arguments_calls_reset) TEST_F(SqliteStatement, get_range_without_arguments_calls_reset)
@@ -1332,7 +1332,7 @@ TEST_F(SqliteStatement, get_values_without_arguments_calls_reset_if_exception_is
EXPECT_CALL(mockStatement, reset()); EXPECT_CALL(mockStatement, reset());
EXPECT_THROW(mockStatement.values<int>(3), Sqlite::StatementHasError); EXPECT_THROW(mockStatement.values<int>(), Sqlite::StatementHasError);
} }
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)
@@ -1372,7 +1372,7 @@ TEST_F(SqliteStatement, get_values_with_simple_arguments_calls_reset)
EXPECT_CALL(mockStatement, reset()); EXPECT_CALL(mockStatement, reset());
mockStatement.values<int>(3, "foo", "bar"); mockStatement.values<int, 3>("foo", "bar");
} }
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)
@@ -1382,7 +1382,7 @@ TEST_F(SqliteStatement, get_values_with_simple_arguments_calls_reset_if_exceptio
EXPECT_CALL(mockStatement, reset()); EXPECT_CALL(mockStatement, reset());
EXPECT_THROW(mockStatement.values<int>(3, "foo", "bar"), Sqlite::StatementHasError); EXPECT_THROW((mockStatement.values<int, 3>("foo", "bar")), Sqlite::StatementHasError);
} }
TEST_F(SqliteStatement, reset_if_write_is_throwing_exception) TEST_F(SqliteStatement, reset_if_write_is_throwing_exception)
@@ -1580,7 +1580,7 @@ TEST_F(SqliteStatement, read_statement_values_with_transactions)
database); database);
database.unlock(); database.unlock();
std::vector<Tuple> values = statement.valuesWithTransaction<Tuple>(1024, "bar", "blah"); std::vector<Tuple> values = statement.valuesWithTransaction<Tuple, 1024>("bar", "blah");
ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1})); ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1}));
database.lock(); database.lock();
@@ -1646,7 +1646,7 @@ TEST_F(SqliteStatement, read_write_statement_values_with_transactions)
"SELECT name, number, value FROM test WHERE name=? AND number=?", database); "SELECT name, number, value FROM test WHERE name=? AND number=?", database);
database.unlock(); database.unlock();
std::vector<Tuple> values = statement.valuesWithTransaction<Tuple>(1024, "bar", "blah"); std::vector<Tuple> values = statement.valuesWithTransaction<Tuple, 1024>("bar", "blah");
ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1})); ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1}));
database.lock(); database.lock();