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 <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2017-09-21 11:43:24 +02:00
parent e88a081213
commit ed2ae5fa81
12 changed files with 250 additions and 289 deletions

View File

@@ -420,7 +420,7 @@ Type DatabaseBackend::toValue(Utils::SmallStringView sqlStatement)
statement.next();
return statement.value<Type>(0);
return statement.fetchValue<Type>(0);
}
} // namespace Sqlite

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -31,6 +31,8 @@
#include <utils/smallstringvector.h>
#include <utils/optional.h>
#include <cstdint>
#include <memory>
#include <type_traits>
@@ -58,16 +60,22 @@ protected:
void execute() const;
void reset() const;
int fetchIntValue(int column) const;
long fetchLongValue(int column) const;
long long fetchLongLongValue(int column) const;
double fetchDoubleValue(int column) const;
Utils::SmallString fetchSmallStringValue(int column) const;
Utils::PathString fetchPathStringValue(int column) const;
template<typename Type>
Type value(int column) const;
Type fetchValue(int column) const;
Utils::SmallString text(int column) const;
int columnCount() const;
Utils::SmallStringVector columnNames() const;
void bind(int index, int value);
void bind(int index, long long value);
void bind(int index, double value);
void bind(int index, Utils::SmallStringView value);
void bind(int index, int fetchValue);
void bind(int index, long long fetchValue);
void bind(int index, double fetchValue);
void bind(int index, Utils::SmallStringView fetchValue);
void bind(int index, uint value)
{
@@ -110,138 +118,60 @@ protected:
}
template <typename Type>
void bind(Utils::SmallStringView name, Type value);
void bind(Utils::SmallStringView name, Type fetchValue);
int bindingIndexForName(Utils::SmallStringView name) const;
void setBindingColumnNames(const Utils::SmallStringVector &bindingColumnNames);
const Utils::SmallStringVector &bindingColumnNames() const;
template <typename... ResultTypes>
std::vector<std::tuple<ResultTypes...>> tupleValues(std::size_t reserveSize)
template <typename ResultType,
int ResultTypeCount = 1>
std::vector<ResultType> values(std::size_t reserveSize)
{
using Container = std::vector<std::tuple<ResultTypes...>>;
Container resultValues;
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
while (next())
emplaceTupleValues<Container, ResultTypes...>(resultValues);
emplaceBackValues<ResultTypeCount>(resultValues);
reset();
return resultValues;
}
template <typename... ResultTypes,
template <typename ResultType,
int ResultTypeCount = 1,
typename... QueryTypes>
std::vector<std::tuple<ResultTypes...>> tupleValues(std::size_t reserveSize, const QueryTypes&... queryValues)
std::vector<ResultType> values(std::size_t reserveSize, const QueryTypes&... queryValues)
{
using Container = std::vector<std::tuple<ResultTypes...>>;
Container resultValues;
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
bindValues(queryValues...);
while (next())
emplaceTupleValues<Container, ResultTypes...>(resultValues);
emplaceBackValues<ResultTypeCount>(resultValues);
reset();
return resultValues;
}
template <typename... ResultTypes,
typename... QueryElementTypes>
std::vector<std::tuple<ResultTypes...>> tupleValues(std::size_t reserveSize,
const std::vector<std::tuple<QueryElementTypes...>> &queryTuples)
{
using Container = std::vector<std::tuple<ResultTypes...>>;
Container resultValues;
resultValues.reserve(reserveSize);
for (const auto &queryTuple : queryTuples) {
bindTupleValues(queryTuple);
while (next())
emplaceTupleValues<Container, ResultTypes...>(resultValues);
reset();
}
return resultValues;
}
template <typename... ResultTypes,
template <typename ResultType,
int ResultTypeCount = 1,
typename QueryElementType>
std::vector<std::tuple<ResultTypes...>> tupleValues(std::size_t reserveSize,
const std::vector<QueryElementType> &queryValues)
{
using Container = std::vector<std::tuple<ResultTypes...>>;
Container resultValues;
resultValues.reserve(reserveSize);
for (const QueryElementType &queryValue : queryValues) {
bindValues(queryValue);
while (next())
emplaceTupleValues<Container, ResultTypes...>(resultValues);
reset();
}
return resultValues;
}
template <typename ResultType,
typename... ResultEntryTypes>
std::vector<ResultType> structValues(std::size_t reserveSize)
{
using Container = std::vector<ResultType>;
Container resultValues;
resultValues.reserve(reserveSize);
while (next())
pushBackStructValues<Container, ResultEntryTypes...>(resultValues);
reset();
return resultValues;
}
template <typename ResultType,
typename... ResultEntryTypes,
typename... QueryTypes>
std::vector<ResultType> structValues(std::size_t reserveSize, const QueryTypes&... queryValues)
{
using Container = std::vector<ResultType>;
Container resultValues;
resultValues.reserve(reserveSize);
bindValues(queryValues...);
while (next())
pushBackStructValues<Container, ResultEntryTypes...>(resultValues);
reset();
return resultValues;
}
template <typename ResultType,
typename... ResultEntryTypes,
typename QueryElementType>
std::vector<ResultType> structValues(std::size_t reserveSize,
std::vector<ResultType> values(std::size_t reserveSize,
const std::vector<QueryElementType> &queryValues)
{
using Container = std::vector<ResultType>;
Container resultValues;
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
for (const QueryElementType &queryValue : queryValues) {
bindValues(queryValue);
while (next())
pushBackStructValues<Container, ResultEntryTypes...>(resultValues);
emplaceBackValues<ResultTypeCount>(resultValues);
reset();
}
@@ -250,9 +180,9 @@ protected:
}
template <typename ResultType,
typename... ResultEntryTypes,
int ResultTypeCount = 1,
typename... QueryElementTypes>
std::vector<ResultType> structValues(std::size_t reserveSize,
std::vector<ResultType> values(std::size_t reserveSize,
const std::vector<std::tuple<QueryElementTypes...>> &queryTuples)
{
using Container = std::vector<ResultType>;
@@ -263,62 +193,7 @@ protected:
bindTupleValues(queryTuple);
while (next())
pushBackStructValues<Container, ResultEntryTypes...>(resultValues);
reset();
}
return resultValues;
}
template <typename ResultType,
typename... ElementTypes>
std::vector<ResultType> values(std::size_t reserveSize)
{
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
while (next())
resultValues.push_back(value<ResultType>(0));
reset();
return resultValues;
}
template <typename ResultType,
typename... ElementType>
std::vector<ResultType> values(std::size_t reserveSize,
const std::vector<std::tuple<ElementType...>> &queryTuples)
{
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
for (const auto &queryTuple : queryTuples) {
bindTupleValues(queryTuple);
while (next())
resultValues.push_back(value<ResultType>(0));
reset();
}
return resultValues;
}
template <typename ResultType,
typename ElementType>
std::vector<ResultType> values(std::size_t reserveSize,
const std::vector<ElementType> &queryValues)
{
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
for (const ElementType &queryValue : queryValues) {
bindValues(queryValue);
while (next())
resultValues.push_back(value<ResultType>(0));
emplaceBackValues<ResultTypeCount>(resultValues);
reset();
}
@@ -327,20 +202,20 @@ protected:
}
template <typename ResultType,
int ResultTypeCount = 1,
typename... QueryTypes>
std::vector<ResultType> values(std::size_t reserveSize, const QueryTypes&... queryValues)
Utils::optional<ResultType> value( const QueryTypes&... queryValues)
{
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
Utils::optional<ResultType> resultValue;
bindValues(queryValues...);
while (next())
resultValues.push_back(value<ResultType>(0));
if (next())
resultValue = assignValue<Utils::optional<ResultType>, ResultTypeCount>();
reset();
return resultValues;
return resultValue;
}
template <typename Type>
@@ -352,7 +227,6 @@ protected:
sqlite3 *sqliteDatabaseHandle() const;
TextEncoding databaseTextEncoding();
bool checkForStepError(int resultCode) const;
void checkForPrepareError(int resultCode) const;
void checkForBindingError(int resultCode) const;
@@ -388,35 +262,74 @@ protected:
DatabaseBackend &databaseBackend);
private:
class ValueGetter
{
public:
ValueGetter(Statement &statement, int column)
: statement(statement),
column(column)
{}
operator int()
{
return statement.fetchIntValue(column);
}
operator long()
{
return statement.fetchLongValue(column);
}
operator long long()
{
return statement.fetchLongLongValue(column);
}
operator double()
{
return statement.fetchDoubleValue(column);
}
operator Utils::SmallString()
{
return statement.fetchSmallStringValue(column);
}
operator Utils::PathString()
{
return statement.fetchPathStringValue(column);
}
Statement &statement;
int column;
};
template <typename ContainerType,
typename... ResultTypes,
int... ColumnIndices>
void emplaceTupleValues(ContainerType &container, std::integer_sequence<int, ColumnIndices...>)
void emplaceBackValues(ContainerType &container, std::integer_sequence<int, ColumnIndices...>)
{
container.emplace_back(value<ResultTypes>(ColumnIndices)...);
container.emplace_back(ValueGetter(*this, ColumnIndices)...);
}
template <typename ContainerType,
typename... ResultTypes>
void emplaceTupleValues(ContainerType &container)
template <int ResultTypeCount,
typename ContainerType>
void emplaceBackValues(ContainerType &container)
{
emplaceTupleValues<ContainerType, ResultTypes...>(container, std::make_integer_sequence<int, sizeof...(ResultTypes)>{});
emplaceBackValues(container, std::make_integer_sequence<int, ResultTypeCount>{});
}
template <typename ContainerType,
typename... ResultEntryTypes,
template <typename ResultOptionalType,
int... ColumnIndices>
void pushBackStructValues(ContainerType &container, std::integer_sequence<int, ColumnIndices...>)
ResultOptionalType assignValue(std::integer_sequence<int, ColumnIndices...>)
{
using ResultType = typename ContainerType::value_type;
container.push_back(ResultType{value<ResultEntryTypes>(ColumnIndices)...});
return ResultOptionalType(Utils::in_place, ValueGetter(*this, ColumnIndices)...);
}
template <typename ContainerType,
typename... ResultEntryTypes>
void pushBackStructValues(ContainerType &container)
template <typename ResultOptionalType,
int ResultTypeCount>
ResultOptionalType assignValue()
{
pushBackStructValues<ContainerType, ResultEntryTypes...>(container, std::make_integer_sequence<int, sizeof...(ResultEntryTypes)>{});
return assignValue<ResultOptionalType>(std::make_integer_sequence<int, ResultTypeCount>{});
}
template<typename ValueType>
@@ -478,10 +391,10 @@ extern template SQLITE_EXPORT long long Statement::toValue<long long>(Utils::Sma
extern template SQLITE_EXPORT double Statement::toValue<double>(Utils::SmallStringView sqlStatement, Database &database);
extern template SQLITE_EXPORT Utils::SmallString Statement::toValue<Utils::SmallString>(Utils::SmallStringView sqlStatement, Database &database);
template <> SQLITE_EXPORT int Statement::value<int>(int column) const;
template <> SQLITE_EXPORT long Statement::value<long>(int column) const;
template <> SQLITE_EXPORT long long Statement::value<long long>(int column) const;
template <> SQLITE_EXPORT double Statement::value<double>(int column) const;
extern template SQLITE_EXPORT Utils::SmallString Statement::value<Utils::SmallString>(int column) const;
extern template SQLITE_EXPORT Utils::PathString Statement::value<Utils::PathString>(int column) const;
template <> SQLITE_EXPORT int Statement::fetchValue<int>(int column) const;
template <> SQLITE_EXPORT long Statement::fetchValue<long>(int column) const;
template <> SQLITE_EXPORT long long Statement::fetchValue<long long>(int column) const;
template <> SQLITE_EXPORT double Statement::fetchValue<double>(int column) const;
extern template SQLITE_EXPORT Utils::SmallString Statement::fetchValue<Utils::SmallString>(int column) const;
extern template SQLITE_EXPORT Utils::PathString Statement::fetchValue<Utils::PathString>(int column) const;
} // namespace Sqlite

View File

@@ -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;
};

View File

@@ -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);