aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libs/sqlite/sqlitebasestatement.h27
-rw-r--r--src/libs/sqlite/sqlitereadstatement.h1
-rw-r--r--src/libs/sqlite/sqlitereadwritestatement.h1
-rw-r--r--tests/unit/unittest/mocksqlitestatement.h3
-rw-r--r--tests/unit/unittest/sqlitestatement-test.cpp59
5 files changed, 90 insertions, 1 deletions
diff --git a/src/libs/sqlite/sqlitebasestatement.h b/src/libs/sqlite/sqlitebasestatement.h
index 3b68d8a3fc..01ae916131 100644
--- a/src/libs/sqlite/sqlitebasestatement.h
+++ b/src/libs/sqlite/sqlitebasestatement.h
@@ -336,6 +336,21 @@ public:
resetter.reset();
}
+ template<int ResultTypeCount = 1, typename Container, typename... QueryTypes>
+ void readTo(Container &container, const QueryTypes &...queryValues)
+ {
+ BaseStatement::checkColumnCount(ResultTypeCount);
+
+ Resetter resetter{*this};
+
+ bindValues(queryValues...);
+
+ while (BaseStatement::next())
+ pushBackToContainer<ResultTypeCount>(container);
+
+ resetter.reset();
+ }
+
protected:
~StatementImplementation() = default;
@@ -430,6 +445,18 @@ private:
return callCallable(callable, std::make_integer_sequence<int, ResultTypeCount>{});
}
+ template<typename Container, int... ColumnIndices>
+ void pushBackToContainer(Container &container, std::integer_sequence<int, ColumnIndices...>)
+ {
+ container.push_back(Container::value_type(ValueGetter(*this, ColumnIndices)...));
+ }
+
+ template<int ResultTypeCount, typename Container>
+ void pushBackToContainer(Container &container)
+ {
+ pushBackToContainer(container, std::make_integer_sequence<int, ResultTypeCount>{});
+ }
+
template<typename ValueType>
void bindValuesByIndex(int index, const ValueType &value)
{
diff --git a/src/libs/sqlite/sqlitereadstatement.h b/src/libs/sqlite/sqlitereadstatement.h
index 9314b54e0f..236aab67f1 100644
--- a/src/libs/sqlite/sqlitereadstatement.h
+++ b/src/libs/sqlite/sqlitereadstatement.h
@@ -35,6 +35,7 @@ public:
explicit ReadStatement(Utils::SmallStringView sqlStatement, Database &database);
using StatementImplementation::readCallback;
+ using StatementImplementation::readTo;
using StatementImplementation::toValue;
using StatementImplementation::value;
using StatementImplementation::values;
diff --git a/src/libs/sqlite/sqlitereadwritestatement.h b/src/libs/sqlite/sqlitereadwritestatement.h
index f7e23e100c..6adc9ebb35 100644
--- a/src/libs/sqlite/sqlitereadwritestatement.h
+++ b/src/libs/sqlite/sqlitereadwritestatement.h
@@ -38,6 +38,7 @@ public:
using StatementImplementation::execute;
using StatementImplementation::readCallback;
+ using StatementImplementation::readTo;
using StatementImplementation::toValue;
using StatementImplementation::value;
using StatementImplementation::values;
diff --git a/tests/unit/unittest/mocksqlitestatement.h b/tests/unit/unittest/mocksqlitestatement.h
index 767840ee8f..141eb9520b 100644
--- a/tests/unit/unittest/mocksqlitestatement.h
+++ b/tests/unit/unittest/mocksqlitestatement.h
@@ -41,9 +41,10 @@ public:
MOCK_CONST_METHOD1(fetchLongValue, long (int));
MOCK_CONST_METHOD1(fetchLongLongValue, long long (int));
MOCK_CONST_METHOD1(fetchDoubleValue, double (int));
- MOCK_CONST_METHOD1(fetchSmallStringValue, Utils::SmallString (int));
+ MOCK_CONST_METHOD1(fetchSmallStringValue, Utils::SmallString(int));
MOCK_CONST_METHOD1(fetchSmallStringViewValue, Utils::SmallStringView(int));
MOCK_CONST_METHOD1(fetchPathStringValue, Utils::PathString (int));
+ MOCK_CONST_METHOD1(fetchValueView, Sqlite::ValueView(int));
template<typename Type>
Type fetchValue(int column) const;
diff --git a/tests/unit/unittest/sqlitestatement-test.cpp b/tests/unit/unittest/sqlitestatement-test.cpp
index 6749742b77..9f14f5b852 100644
--- a/tests/unit/unittest/sqlitestatement-test.cpp
+++ b/tests/unit/unittest/sqlitestatement-test.cpp
@@ -37,6 +37,7 @@
#include <QDir>
+#include <deque>
#include <vector>
namespace {
@@ -1032,4 +1033,62 @@ TEST_F(SqliteStatement, ReadCallbackCallsResetIfExceptionIsThrown)
Sqlite::StatementHasError);
}
+TEST_F(SqliteStatement, ReadToContainer)
+{
+ std::deque<FooValue> values;
+ ReadStatement statement("SELECT number FROM test", database);
+
+ statement.readTo<1>(values);
+
+ ASSERT_THAT(values, UnorderedElementsAre(Eq("blah"), Eq(23.3), Eq(40)));
+}
+
+TEST_F(SqliteStatement, ReadToContainerCallCallbackWithArguments)
+{
+ std::deque<FooValue> values;
+ ReadStatement statement("SELECT number FROM test WHERE value=?", database);
+
+ statement.readTo(values, 2);
+
+ ASSERT_THAT(values, ElementsAre(Eq(23.3)));
+}
+
+TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForToManyArgumentsForReadTo)
+{
+ std::deque<FooValue> values;
+ SqliteTestStatement statement("SELECT name, number FROM test", database);
+
+ ASSERT_THROW(statement.readTo<1>(values, 2), Sqlite::ColumnCountDoesNotMatch);
+}
+
+TEST_F(SqliteStatement, ReadToCallsResetAfterPushingAllValuesBack)
+{
+ std::deque<FooValue> values;
+ MockSqliteStatement mockStatement;
+
+ EXPECT_CALL(mockStatement, reset());
+
+ mockStatement.readTo(values);
+}
+
+TEST_F(SqliteStatement, ReadToThrowsForError)
+{
+ std::deque<FooValue> values;
+ MockSqliteStatement mockStatement;
+ ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
+
+ ASSERT_THROW(mockStatement.readTo(values), Sqlite::StatementHasError);
+}
+
+TEST_F(SqliteStatement, ReadToCallsResetIfExceptionIsThrown)
+{
+ std::deque<FooValue> values;
+ MockSqliteStatement mockStatement;
+ ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
+
+ EXPECT_CALL(mockStatement, reset());
+
+ EXPECT_THROW(mockStatement.readTo(values), Sqlite::StatementHasError);
+}
+
} // namespace