Sqlite: Improve Sqlite wrapper

It is now possible to read values at once.

for (auto [name, value] : statement.tupleValues<String, int>(1000, "foo", 20))
   ....

Change-Id: I3d4bc5218810b4620e1df625126aa490f30bbc71
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2017-08-17 15:33:25 +02:00
parent 8617f497bc
commit 1a25b61576
24 changed files with 769 additions and 277 deletions

View File

@@ -29,13 +29,11 @@
#include "sqlitedatabasebackend.h"
#include "sqliteexception.h"
#include <QMutex>
#include <QtGlobal>
#include <QVariant>
#include <QWaitCondition>
#include "sqlite3.h"
#include <condition_variable>
#include <mutex>
#if defined(__GNUC__)
# pragma GCC diagnostic ignored "-Wignored-qualifiers"
#endif
@@ -61,8 +59,8 @@ void SqliteStatement::deleteCompiledStatement(sqlite3_stmt *compiledStatement)
sqlite3_finalize(compiledStatement);
}
class UnlockNotification {
class UnlockNotification
{
public:
static void unlockNotifyCallBack(void **arguments, int argumentCount)
{
@@ -74,27 +72,24 @@ public:
void wakeupWaitCondition()
{
mutex.lock();
fired = 1;
waitCondition.wakeAll();
mutex.unlock();
{
std::lock_guard<std::mutex> lock(m_mutex);
m_fired = 1;
}
m_waitCondition.notify_all();
}
void wait()
{
mutex.lock();
std::unique_lock<std::mutex> lock(m_mutex);
if (!fired) {
waitCondition.wait(&mutex);
}
mutex.unlock();
m_waitCondition.wait(lock, [&] () { return m_fired; });
}
private:
bool fired = false;
QWaitCondition waitCondition;
QMutex mutex;
bool m_fired = false;
std::condition_variable m_waitCondition;
std::mutex m_mutex;
};
void SqliteStatement::waitForUnlockNotify() const
@@ -143,6 +138,7 @@ void SqliteStatement::step() const
void SqliteStatement::execute() const
{
next();
reset();
}
int SqliteStatement::columnCount() const
@@ -168,7 +164,7 @@ void SqliteStatement::bind(int index, int value)
throwException("SqliteStatement::bind: cant' bind 32 bit integer!");
}
void SqliteStatement::bind(int index, qint64 value)
void SqliteStatement::bind(int index, long long value)
{
int resultCode = sqlite3_bind_int64(m_compiledStatement.get(), index, value);
if (resultCode != SQLITE_OK)
@@ -198,7 +194,8 @@ void SqliteStatement::bind(Utils::SmallStringView name, Type value)
}
template SQLITE_EXPORT void SqliteStatement::bind(Utils::SmallStringView name, int value);
template SQLITE_EXPORT void SqliteStatement::bind(Utils::SmallStringView name, qint64 value);
template SQLITE_EXPORT void SqliteStatement::bind(Utils::SmallStringView name, long value);
template SQLITE_EXPORT void SqliteStatement::bind(Utils::SmallStringView name, long long value);
template SQLITE_EXPORT void SqliteStatement::bind(Utils::SmallStringView name, double value);
template SQLITE_EXPORT void SqliteStatement::bind(Utils::SmallStringView name, Utils::SmallStringView text);
@@ -363,21 +360,23 @@ SqliteDatabase &SqliteStatement::database() const
return m_database;
}
static Utils::SmallString textForColumn(sqlite3_stmt *sqlStatment, int column)
template <typename StringType>
static StringType textForColumn(sqlite3_stmt *sqlStatment, int column)
{
const char *text = reinterpret_cast<const char*>(sqlite3_column_text(sqlStatment, column));
std::size_t size = std::size_t(sqlite3_column_bytes(sqlStatment, column));
return Utils::SmallString(text, size);
return StringType(text, size);
}
static Utils::SmallString convertToTextForColumn(sqlite3_stmt *sqlStatment, int column)
template <typename StringType>
static StringType convertToTextForColumn(sqlite3_stmt *sqlStatment, int column)
{
int dataType = sqlite3_column_type(sqlStatment, column);
switch (dataType) {
case SQLITE_INTEGER:
case SQLITE_FLOAT:
case SQLITE3_TEXT: return textForColumn(sqlStatment, column);
case SQLITE3_TEXT: return textForColumn<StringType>(sqlStatment, column);
case SQLITE_BLOB:
case SQLITE_NULL: return {};
}
@@ -394,7 +393,13 @@ int SqliteStatement::value<int>(int column) const
}
template<>
qint64 SqliteStatement::value<qint64>(int column) const
long SqliteStatement::value<long>(int column) const
{
return long(value<long long>(column));
}
template<>
long long SqliteStatement::value<long long>(int column) const
{
checkIfIsReadyToFetchValues();
checkColumnIsValid(column);
@@ -409,14 +414,17 @@ double SqliteStatement::value<double>(int column) const
return sqlite3_column_double(m_compiledStatement.get(), column);
}
template<>
Utils::SmallString SqliteStatement::value<Utils::SmallString>(int column) const
template<typename StringType>
StringType SqliteStatement::value(int column) const
{
checkIfIsReadyToFetchValues();
checkColumnIsValid(column);
return convertToTextForColumn(m_compiledStatement.get(), column);
return convertToTextForColumn<StringType>(m_compiledStatement.get(), column);
}
template SQLITE_EXPORT Utils::SmallString SqliteStatement::value<Utils::SmallString>(int column) const;
template SQLITE_EXPORT Utils::PathString SqliteStatement::value<Utils::PathString>(int column) const;
Utils::SmallString SqliteStatement::text(int column) const
{
return value<Utils::SmallString>(column);
@@ -434,45 +442,6 @@ ContainerType SqliteStatement::columnValues(const std::vector<int> &columnIndice
return valueContainer;
}
template <typename ContainerType>
ContainerType SqliteStatement::values(const std::vector<int> &columns, int size) const
{
checkColumnsAreValid(columns);
ContainerType resultValues;
resultValues.reserve(typename ContainerType::size_type(size));
reset();
while (next()) {
auto values = columnValues<ContainerType>(columns);
std::move(values.begin(), values.end(), std::back_inserter(resultValues));
}
return resultValues;
}
template SQLITE_EXPORT Utils::SmallStringVector SqliteStatement::values<Utils::SmallStringVector>(const std::vector<int> &columnIndices, int size) const;
template <typename ContainerType>
ContainerType SqliteStatement::values(int column) const
{
typedef typename ContainerType::value_type ElementType;
ContainerType resultValues;
reset();
while (next()) {
resultValues.push_back(value<ElementType>(column));
}
return resultValues;
}
template SQLITE_EXPORT std::vector<qint64> SqliteStatement::values<std::vector<qint64>>(int column) const;
template SQLITE_EXPORT std::vector<double> SqliteStatement::values<std::vector<double>>(int column) const;
template SQLITE_EXPORT Utils::SmallStringVector SqliteStatement::values<Utils::SmallStringVector>(int column) const;
template <typename Type>
Type SqliteStatement::toValue(Utils::SmallStringView sqlStatement, SqliteDatabase &database)
{
@@ -484,7 +453,7 @@ Type SqliteStatement::toValue(Utils::SmallStringView sqlStatement, SqliteDatabas
}
template SQLITE_EXPORT int SqliteStatement::toValue<int>(Utils::SmallStringView sqlStatement, SqliteDatabase &database);
template SQLITE_EXPORT qint64 SqliteStatement::toValue<qint64>(Utils::SmallStringView sqlStatement, SqliteDatabase &database);
template SQLITE_EXPORT long long SqliteStatement::toValue<long long>(Utils::SmallStringView sqlStatement, SqliteDatabase &database);
template SQLITE_EXPORT double SqliteStatement::toValue<double>(Utils::SmallStringView sqlStatement, SqliteDatabase &database);
template SQLITE_EXPORT Utils::SmallString SqliteStatement::toValue<Utils::SmallString>(Utils::SmallStringView sqlStatement, SqliteDatabase &database);