Commit ed2ae5fa authored by Marco Bubke's avatar Marco Bubke

Sqlite: Improve SqliteStatement

There are now only value and values methods. value returns an optional
and values are returning a vector. The result value count has now be
specified instead of the result value list.

Change-Id: I17a0741d5e838b4bf4b9486825c870ada1722584
Reviewed-by: Tim Jenssen's avatarTim Jenssen <tim.jenssen@qt.io>
parent e88a0812
......@@ -420,7 +420,7 @@ Type DatabaseBackend::toValue(Utils::SmallStringView sqlStatement)
statement.next();
return statement.value<Type>(0);
return statement.fetchValue<Type>(0);
}
} // namespace Sqlite
......@@ -34,8 +34,7 @@ class SQLITE_EXPORT ReadStatement final : private Statement
public:
explicit ReadStatement(Utils::SmallStringView sqlStatement, Database &database);
using Statement::structValues;
using Statement::tupleValues;
using Statement::value;
using Statement::values;
using Statement::toValue;
using Statement::database;
......
......@@ -37,9 +37,8 @@ public:
ReadWriteStatement(Utils::SmallStringView sqlStatement, Database &database);
using Statement::execute;
using Statement::value;
using Statement::values;
using Statement::structValues;
using Statement::tupleValues;
using Statement::toValue;
using Statement::database;
using Statement::write;
......
......@@ -445,8 +445,7 @@ static StringType convertToTextForColumn(sqlite3_stmt *sqlStatment, int column)
Q_UNREACHABLE();
}
template<>
int Statement::value<int>(int column) const
int Statement::fetchIntValue(int column) const
{
checkIfIsReadyToFetchValues();
checkColumnIsValid(column);
......@@ -454,13 +453,23 @@ int Statement::value<int>(int column) const
}
template<>
long Statement::value<long>(int column) const
int Statement::fetchValue<int>(int column) const
{
return long(value<long long>(column));
return fetchIntValue(column);
}
long Statement::fetchLongValue(int column) const
{
return long(fetchValue<long long>(column));
}
template<>
long long Statement::value<long long>(int column) const
long Statement::fetchValue<long>(int column) const
{
return fetchLongValue(column);
}
long long Statement::fetchLongLongValue(int column) const
{
checkIfIsReadyToFetchValues();
checkColumnIsValid(column);
......@@ -468,27 +477,48 @@ long long Statement::value<long long>(int column) const
}
template<>
double Statement::value<double>(int column) const
long long Statement::fetchValue<long long>(int column) const
{
return fetchLongLongValue(column);
}
double Statement::fetchDoubleValue(int column) const
{
checkIfIsReadyToFetchValues();
checkColumnIsValid(column);
return sqlite3_column_double(m_compiledStatement.get(), column);
}
template<>
double Statement::fetchValue<double>(int column) const
{
return fetchDoubleValue(column);
}
template<typename StringType>
StringType Statement::value(int column) const
StringType Statement::fetchValue(int column) const
{
checkIfIsReadyToFetchValues();
checkColumnIsValid(column);
return convertToTextForColumn<StringType>(m_compiledStatement.get(), column);
}
template SQLITE_EXPORT Utils::SmallString Statement::value<Utils::SmallString>(int column) const;
template SQLITE_EXPORT Utils::PathString Statement::value<Utils::PathString>(int column) const;
Utils::SmallString Statement::fetchSmallStringValue(int column) const
{
return fetchValue<Utils::SmallString>(column);
}
Utils::PathString Statement::fetchPathStringValue(int column) const
{
return fetchValue<Utils::PathString>(column);
}
template SQLITE_EXPORT Utils::SmallString Statement::fetchValue<Utils::SmallString>(int column) const;
template SQLITE_EXPORT Utils::PathString Statement::fetchValue<Utils::PathString>(int column) const;
Utils::SmallString Statement::text(int column) const
{
return value<Utils::SmallString>(column);
return fetchValue<Utils::SmallString>(column);
}
template <typename ContainerType>
......@@ -498,7 +528,7 @@ ContainerType Statement::columnValues(const std::vector<int> &columnIndices) con
ContainerType valueContainer;
valueContainer.reserve(columnIndices.size());
for (int columnIndex : columnIndices)
valueContainer.push_back(value<ElementType>(columnIndex));
valueContainer.push_back(fetchValue<ElementType>(columnIndex));
return valueContainer;
}
......@@ -510,7 +540,7 @@ Type Statement::toValue(Utils::SmallStringView sqlStatement, Database &database)
statement.next();
return statement.value<Type>(0);
return statement.fetchValue<Type>(0);
}
template SQLITE_EXPORT int Statement::toValue<int>(Utils::SmallStringView sqlStatement, Database &database);
......
This diff is collapsed.
......@@ -39,24 +39,25 @@ class SourceLocations
public:
struct Location
{
qint64 sourceId;
qint64 line;
qint64 column;
Location(qint64 sourceId, qint64 line, qint64 column)
: sourceId(sourceId), line(line), column(column)
{}
qint64 sourceId;
qint64 line;
qint64 column;
};
struct Source
{
Source(qint64 sourceId, Utils::PathString &&sourcePath)
: sourceId(sourceId), sourcePath(std::move(sourcePath))
{}
qint64 sourceId;
Utils::PathString sourcePath;
};
enum LocationGetter
{
SourceId = 0,
Line,
Column
};
std::vector<Location> locations;
std::unordered_map<qint64, Utils::PathString> sources;
};
......
......@@ -52,7 +52,7 @@ public:
const std::size_t reserveSize = 128;
auto locations = locationsStatement.template structValues<Location, qint64, qint64, qint64>(
auto locations = locationsStatement.template values<Location, 3>(
reserveSize,
filePath,
line,
......@@ -62,7 +62,7 @@ public:
ReadStatement &sourcesStatement = m_statementFactory.selectSourcePathForId;
auto sources = sourcesStatement.template structValues<Source, qint64, Utils::PathString>(
auto sources = sourcesStatement.template values<Source, 2>(
reserveSize,
sourceIds);
......
......@@ -25,31 +25,6 @@
#include "mocksqlitereadstatement.h"
template <typename ResultType,
typename... QueryType>
std::vector<ResultType> values(std::size_t, QueryType...)
{
FAIL() << "MockSqliteReadStatement::value was instanciated implicitly. Please add an explicit overload.";
}
template <typename... ResultType>
std::vector<std::tuple<ResultType...>> values(std::size_t,
Utils::SmallStringView,
uint,
uint)
{
FAIL() << "MockSqliteReadStatement::value was instanciated implicitly. Please add an explicit overload.";
}
template <typename... ResultType,
template <typename...> class ContainerType,
typename ElementType>
std::vector<std::tuple<ResultType...>> tupleValues(std::size_t,
const ContainerType<ElementType> &)
{
FAIL() << "MockSqliteReadStatement::value was instanciated implicitly. Please add an explicit overload.";
}
template <>
std::vector<FilePathIndex> MockSqliteReadStatement::values<FilePathIndex>(std::size_t reserveSize)
{
......@@ -58,20 +33,24 @@ std::vector<FilePathIndex> MockSqliteReadStatement::values<FilePathIndex>(std::s
template <>
std::vector<Location>
MockSqliteReadStatement::structValues<Location, qint64, qint64, qint64>(
std::size_t reserveSize,
const Utils::PathString &sourcePath,
const uint &line,
const uint &column)
MockSqliteReadStatement::values<Location, 3>(std::size_t reserveSize,
const Utils::PathString &sourcePath,
const uint &line,
const uint &column)
{
return structValuesReturnStdVectorLocation(reserveSize, sourcePath, line, column);
return valuesReturnStdVectorLocation(reserveSize, sourcePath, line, column);
}
template <>
std::vector<Source>
MockSqliteReadStatement::structValues<Source, qint64, Utils::PathString>(
std::size_t reserveSize,
const std::vector<qint64> &sourceIds)
MockSqliteReadStatement::values<Source, 2>(std::size_t reserveSize, const std::vector<qint64> &sourceIds)
{
return valuesReturnStdVectorSource(reserveSize, sourceIds);
}
template <>
Utils::optional<uint32_t>
MockSqliteReadStatement::value<uint32_t>(const Utils::SmallStringView &text)
{
return structValuesReturnStdVectorSource(reserveSize, sourceIds);
return valueReturnUInt32(text);
}
......@@ -31,6 +31,7 @@
#include "mocksqlitedatabase.h"
#include <utils/optional.h>
#include <utils/smallstring.h>
#include <cstdint>
......@@ -53,28 +54,31 @@ public:
MOCK_CONST_METHOD1(valuesReturnStdVectorInt,
std::vector<FilePathIndex>(std::size_t));
MOCK_CONST_METHOD4(structValuesReturnStdVectorLocation,
MOCK_CONST_METHOD4(valuesReturnStdVectorLocation,
std::vector<Location>(std::size_t, Utils::SmallStringView, qint64, qint64));
MOCK_CONST_METHOD2(structValuesReturnStdVectorSource,
MOCK_CONST_METHOD2(valuesReturnStdVectorSource,
std::vector<Source>(std::size_t, const std::vector<qint64> &));
template <typename ResultType,
typename... QueryType>
std::vector<ResultType> values(std::size_t, QueryType...);
MOCK_CONST_METHOD1(valueReturnUInt32,
Utils::optional<uint32_t>(Utils::SmallStringView));
template <typename ResultType,
typename... ResultEntryType,
int ResultTypeCount = 1,
typename... QueryType>
std::vector<ResultType> structValues(std::size_t reserveSize, const QueryType&... queryValues);
std::vector<ResultType> values(std::size_t reserveSize, const QueryType&... queryValues);
template <typename ResultType,
typename... ResultEntryType,
int ResultTypeCount = 1,
template <typename...> class QueryContainerType,
typename QueryElementType>
std::vector<ResultType> structValues(std::size_t reserveSize,
const QueryContainerType<QueryElementType> &queryValues);
std::vector<ResultType> values(std::size_t reserveSize,
const QueryContainerType<QueryElementType> &queryValues);
template <typename ResultType,
typename... QueryTypes>
Utils::optional<ResultType> value(const QueryTypes&... queryValues);
public:
Utils::SmallString sqlStatement;
......@@ -85,7 +89,7 @@ std::vector<int> MockSqliteReadStatement::values<int>(std::size_t reserveSize);
template <>
std::vector<Location>
MockSqliteReadStatement::structValues<Location, qint64, qint64, qint64>(
MockSqliteReadStatement::values<Location, 3>(
std::size_t reserveSize,
const Utils::PathString &sourcePath,
const uint &line,
......@@ -93,8 +97,11 @@ MockSqliteReadStatement::structValues<Location, qint64, qint64, qint64>(
template <>
std::vector<Source>
MockSqliteReadStatement::structValues<Source, qint64, Utils::PathString>(
MockSqliteReadStatement::values<Source, 2>(
std::size_t reserveSize,
const std::vector<qint64> &);
template <>
Utils::optional<uint32_t>
MockSqliteReadStatement::value<uint32_t>(const Utils::SmallStringView&);
......@@ -75,6 +75,10 @@ protected:
struct Output
{
Output(Utils::SmallString name, Utils::SmallString number, long long value)
: name(name), number(number), value(value)
{}
Utils::SmallString name;
Utils::SmallString number;
long long value;
......@@ -124,13 +128,13 @@ TEST_F(SqliteStatement, Value)
statement.next();
ASSERT_THAT(statement.value<int>(0), 0);
ASSERT_THAT(statement.value<int64_t>(0), 0);
ASSERT_THAT(statement.value<double>(0), 0.0);
ASSERT_THAT(statement.fetchValue<int>(0), 0);
ASSERT_THAT(statement.fetchValue<int64_t>(0), 0);
ASSERT_THAT(statement.fetchValue<double>(0), 0.0);
ASSERT_THAT(statement.text(0), "foo");
ASSERT_THAT(statement.value<int>(1), 23);
ASSERT_THAT(statement.value<int64_t>(1), 23);
ASSERT_THAT(statement.value<double>(1), 23.3);
ASSERT_THAT(statement.fetchValue<int>(1), 23);
ASSERT_THAT(statement.fetchValue<int64_t>(1), 23);
ASSERT_THAT(statement.fetchValue<double>(1), 23.3);
ASSERT_THAT(statement.text(1), "23.3");
}
......@@ -138,7 +142,7 @@ TEST_F(SqliteStatement, ThrowNoValuesToFetchForNotSteppedStatement)
{
SqliteTestStatement statement("SELECT name, number FROM test", database);
ASSERT_THROW(statement.value<int>(0), Sqlite::NoValuesToFetch);
ASSERT_THROW(statement.fetchValue<int>(0), Sqlite::NoValuesToFetch);
}
TEST_F(SqliteStatement, ThrowNoValuesToFetchForDoneStatement)
......@@ -146,7 +150,7 @@ TEST_F(SqliteStatement, ThrowNoValuesToFetchForDoneStatement)
SqliteTestStatement statement("SELECT name, number FROM test", database);
while (statement.next()) {}
ASSERT_THROW(statement.value<int>(0), Sqlite::NoValuesToFetch);
ASSERT_THROW(statement.fetchValue<int>(0), Sqlite::NoValuesToFetch);
}
TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForNegativeColumn)
......@@ -154,7 +158,7 @@ TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForNegativeColumn)
SqliteTestStatement statement("SELECT name, number FROM test", database);
statement.next();
ASSERT_THROW(statement.value<int>(-1), Sqlite::InvalidColumnFetched);
ASSERT_THROW(statement.fetchValue<int>(-1), Sqlite::InvalidColumnFetched);
}
TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForNotExistingColumn)
......@@ -162,7 +166,7 @@ TEST_F(SqliteStatement, ThrowInvalidColumnFetchedForNotExistingColumn)
SqliteTestStatement statement("SELECT name, number FROM test", database);
statement.next();
ASSERT_THROW(statement.value<int>(2), Sqlite::InvalidColumnFetched);
ASSERT_THROW(statement.fetchValue<int>(2), Sqlite::InvalidColumnFetched);
}
TEST_F(SqliteStatement, ToIntergerValue)
......@@ -206,7 +210,7 @@ TEST_F(SqliteStatement, BindString)
statement.next();
ASSERT_THAT(statement.text(0), "foo");
ASSERT_THAT(statement.value<double>(1), 23.3);
ASSERT_THAT(statement.fetchValue<double>(1), 23.3);
}
TEST_F(SqliteStatement, BindInteger)
......@@ -356,7 +360,7 @@ TEST_F(SqliteStatement, GetTupleValuesWithoutArguments)
using Tuple = std::tuple<Utils::SmallString, double, int>;
ReadStatement statement("SELECT name, number, value FROM test", database);
auto values = statement.tupleValues<Utils::SmallString, double, int>(3);
auto values = statement.values<Tuple, 3>(3);
ASSERT_THAT(values, ElementsAre(Tuple{"bar", 0, 1},
Tuple{"foo", 23.3, 2},
......@@ -376,7 +380,7 @@ TEST_F(SqliteStatement, GetStructValuesWithoutArguments)
{
ReadStatement statement("SELECT name, number, value FROM test", database);
auto values = statement.structValues<Output, Utils::SmallString, Utils::SmallString, long long>(3);
auto values = statement.values<Output, 3>(3);
ASSERT_THAT(values, ElementsAre(Output{"bar", "blah", 1},
Output{"foo", "23.3", 2},
......@@ -399,7 +403,7 @@ TEST_F(SqliteStatement, GetValuesForMultipleOutputValuesAndContainerQueryValues)
std::vector<double> queryValues = {40, 23.3};
ReadStatement statement("SELECT name, number, value FROM test WHERE number=?", database);
auto values = statement.tupleValues<Utils::SmallString, double, double>(3, queryValues);
auto values = statement.values<Tuple, 3>(3, queryValues);
ASSERT_THAT(values, ElementsAre(Tuple{"poo", 40, 3.},
Tuple{"foo", 23.3, 2.}));
......@@ -418,14 +422,14 @@ TEST_F(SqliteStatement, GetValuesForSingleOutputValuesAndContainerQueryValues)
TEST_F(SqliteStatement, GetValuesForMultipleOutputValuesAndContainerQueryTupleValues)
{
using Tuple = std::tuple<Utils::SmallString, Utils::SmallString, int>;
using Tuple2 = std::tuple<Utils::SmallString, double, int>;
using ResultTuple = std::tuple<Utils::SmallString, double, int>;
std::vector<Tuple> queryValues = {{"poo", "40", 3}, {"bar", "blah", 1}};
ReadStatement statement("SELECT name, number, value FROM test WHERE name= ? AND number=? AND value=?", database);
auto values = statement.tupleValues<Utils::SmallString, double, int>(3, queryValues);
auto values = statement.values<ResultTuple, 3>(3, queryValues);
ASSERT_THAT(values, ElementsAre(Tuple2{"poo", 40, 3},
Tuple2{"bar", 0, 1}));
ASSERT_THAT(values, ElementsAre(ResultTuple{"poo", 40, 3},
ResultTuple{"bar", 0, 1}));
}
TEST_F(SqliteStatement, GetValuesForSingleOutputValuesAndContainerQueryTupleValues)
......@@ -444,7 +448,7 @@ TEST_F(SqliteStatement, GetValuesForMultipleOutputValuesAndMultipleQueryValue)
using Tuple = std::tuple<Utils::SmallString, Utils::SmallString, long long>;
ReadStatement statement("SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database);
auto values = statement.tupleValues<Utils::SmallString, Utils::SmallString, long long>(3, "bar", "blah", 1);
auto values = statement.values<Tuple, 3>(3, "bar", "blah", 1);
ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1}));
}
......@@ -453,9 +457,9 @@ TEST_F(SqliteStatement, CallGetValuesForMultipleOutputValuesAndMultipleQueryValu
{
using Tuple = std::tuple<Utils::SmallString, Utils::SmallString, long long>;
ReadStatement statement("SELECT name, number, value FROM test WHERE name=? AND number=?", database);
statement.tupleValues<Utils::SmallString, Utils::SmallString, long long>(3, "bar", "blah");
statement.values<Tuple, 3>(3, "bar", "blah");
auto values = statement.tupleValues<Utils::SmallString, Utils::SmallString, long long>(3, "bar", "blah");
auto values = statement.values<Tuple, 3>(3, "bar", "blah");
ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1}));
}
......@@ -464,7 +468,7 @@ TEST_F(SqliteStatement, GetStructOutputValuesAndMultipleQueryValue)
{
ReadStatement statement("SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database);
auto values = statement.structValues<Output, Utils::SmallString, Utils::SmallString, long long>(3, "bar", "blah", 1);
auto values = statement.values<Output, 3>(3, "bar", "blah", 1);
ASSERT_THAT(values, ElementsAre(Output{"bar", "blah", 1}));
}
......@@ -474,7 +478,7 @@ TEST_F(SqliteStatement, GetStructOutputValuesAndContainerQueryValues)
std::vector<double> queryValues = {40, 23.3};
ReadStatement statement("SELECT name, number, value FROM test WHERE number=?", database);
auto values = statement.structValues<Output, Utils::SmallString, Utils::SmallString, long long>(3, queryValues);
auto values = statement.values<Output, 3>(3, queryValues);
ASSERT_THAT(values, ElementsAre(Output{"poo", "40", 3},
Output{"foo", "23.3", 2}));
......@@ -486,12 +490,41 @@ TEST_F(SqliteStatement, GetStructOutputValuesAndContainerQueryTupleValues)
std::vector<Tuple> queryValues = {{"poo", "40", 3}, {"bar", "blah", 1}};
ReadStatement statement("SELECT name, number, value FROM test WHERE name= ? AND number=? AND value=?", database);
auto values = statement.structValues<Output, Utils::SmallString, Utils::SmallString, long long>(3, queryValues);
auto values = statement.values<Output, 3>(3, queryValues);
ASSERT_THAT(values, ElementsAre(Output{"poo", "40", 3},
Output{"bar", "blah", 1}));
}
TEST_F(SqliteStatement, GetOptionalSingleValueAndMultipleQueryValue)
{
ReadStatement statement("SELECT name FROM test WHERE name=? AND number=? AND value=?", database);
auto value = statement.value<Utils::SmallString>("bar", "blah", 1);
ASSERT_THAT(value.value(), Eq("bar"));
}
TEST_F(SqliteStatement, GetOptionalOutputValueAndMultipleQueryValue)
{
ReadStatement statement("SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database);
auto value = statement.value<Output, 3>("bar", "blah", 1);
ASSERT_THAT(value.value(), Eq(Output{"bar", "blah", 1}));
}
TEST_F(SqliteStatement, GetOptionalTupleValueAndMultipleQueryValue)
{
using Tuple = std::tuple<Utils::SmallString, Utils::SmallString, long long>;
ReadStatement statement("SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database);
auto value = statement.value<Tuple, 3>("bar", "blah", 1);
ASSERT_THAT(value.value(), Eq(Tuple{"bar", "blah", 1}));
}
void SqliteStatement::SetUp()
{
database.setJournalMode(JournalMode::Memory);
......
......@@ -46,7 +46,7 @@ public:
using Statement::execute;
using Statement::next;
using Statement::text;
using Statement::value;
using Statement::fetchValue;
protected:
void checkIsWritableStatement();
......
......@@ -63,9 +63,9 @@ protected:
TEST_F(SymbolQuery, LocationsAt)
{
EXPECT_CALL(selectLocationsForSymbolLocation, structValuesReturnStdVectorLocation(_, Eq("/path/to/file.cpp"), 14, 7))
EXPECT_CALL(selectLocationsForSymbolLocation, valuesReturnStdVectorLocation(_, Eq("/path/to/file.cpp"), 14, 7))
.WillRepeatedly(Return(locations));
EXPECT_CALL(selectSourcePathForId, structValuesReturnStdVectorSource(_, ElementsAre(1, 2, 4)));
EXPECT_CALL(selectSourcePathForId, valuesReturnStdVectorSource(_, ElementsAre(1, 2, 4)));
query.locationsAt("/path/to/file.cpp", 14, 7);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment