forked from qt-creator/qt-creator
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:
@@ -28,12 +28,11 @@
|
||||
namespace Sqlite {
|
||||
|
||||
CreateTableSqlStatementBuilder::CreateTableSqlStatementBuilder()
|
||||
: m_sqlStatementBuilder("CREATE TABLE IF NOT EXISTS $table($columnDefinitions)$withoutRowId"),
|
||||
m_useWithoutRowId(false)
|
||||
: m_sqlStatementBuilder("CREATE $temporaryTABLE $ifNotExits$table($columnDefinitions)$withoutRowId")
|
||||
{
|
||||
}
|
||||
|
||||
void CreateTableSqlStatementBuilder::setTable(Utils::SmallString &&tableName)
|
||||
void CreateTableSqlStatementBuilder::setTableName(Utils::SmallString &&tableName)
|
||||
{
|
||||
m_sqlStatementBuilder.clear();
|
||||
|
||||
@@ -42,11 +41,11 @@ void CreateTableSqlStatementBuilder::setTable(Utils::SmallString &&tableName)
|
||||
|
||||
void CreateTableSqlStatementBuilder::addColumn(Utils::SmallString &&columnName,
|
||||
ColumnType columnType,
|
||||
IsPrimaryKey isPrimaryKey)
|
||||
Contraint constraint)
|
||||
{
|
||||
m_sqlStatementBuilder.clear();
|
||||
|
||||
m_columns.emplace_back(std::move(columnName), columnType, isPrimaryKey);
|
||||
m_columns.emplace_back(std::move(columnName), columnType, constraint);
|
||||
}
|
||||
|
||||
void CreateTableSqlStatementBuilder::setColumns(const SqliteColumns &columns)
|
||||
@@ -61,6 +60,16 @@ void CreateTableSqlStatementBuilder::setUseWithoutRowId(bool useWithoutRowId)
|
||||
m_useWithoutRowId = useWithoutRowId;
|
||||
}
|
||||
|
||||
void CreateTableSqlStatementBuilder::setUseIfNotExists(bool useIfNotExists)
|
||||
{
|
||||
m_useIfNotExits = useIfNotExists;
|
||||
}
|
||||
|
||||
void CreateTableSqlStatementBuilder::setUseTemporaryTable(bool useTemporaryTable)
|
||||
{
|
||||
m_useTemporaryTable = useTemporaryTable;
|
||||
}
|
||||
|
||||
void CreateTableSqlStatementBuilder::clear()
|
||||
{
|
||||
m_sqlStatementBuilder.clear();
|
||||
@@ -95,8 +104,11 @@ void CreateTableSqlStatementBuilder::bindColumnDefinitions() const
|
||||
for (const SqliteColumn &columns : m_columns) {
|
||||
Utils::SmallString columnDefinitionString = {columns.name(), " ", columns.typeString()};
|
||||
|
||||
if (columns.isPrimaryKey())
|
||||
columnDefinitionString.append(" PRIMARY KEY");
|
||||
switch (columns.constraint()) {
|
||||
case Contraint::PrimaryKey: columnDefinitionString.append(" PRIMARY KEY"); break;
|
||||
case Contraint::Unique: columnDefinitionString.append(" UNIQUE"); break;
|
||||
case Contraint::NoConstraint: break;
|
||||
}
|
||||
|
||||
columnDefinitionStrings.push_back(columnDefinitionString);
|
||||
}
|
||||
@@ -108,12 +120,34 @@ void CreateTableSqlStatementBuilder::bindAll() const
|
||||
{
|
||||
m_sqlStatementBuilder.bind("$table", m_tableName.clone());
|
||||
|
||||
bindTemporary();
|
||||
bindIfNotExists();
|
||||
bindColumnDefinitions();
|
||||
bindWithoutRowId();
|
||||
}
|
||||
|
||||
void CreateTableSqlStatementBuilder::bindWithoutRowId() const
|
||||
{
|
||||
if (m_useWithoutRowId)
|
||||
m_sqlStatementBuilder.bind("$withoutRowId", " WITHOUT ROWID");
|
||||
else
|
||||
m_sqlStatementBuilder.bindEmptyText("$withoutRowId");
|
||||
}
|
||||
|
||||
void CreateTableSqlStatementBuilder::bindIfNotExists() const
|
||||
{
|
||||
if (m_useIfNotExits)
|
||||
m_sqlStatementBuilder.bind("$ifNotExits", "IF NOT EXISTS ");
|
||||
else
|
||||
m_sqlStatementBuilder.bindEmptyText("$ifNotExits");
|
||||
}
|
||||
|
||||
void CreateTableSqlStatementBuilder::bindTemporary() const
|
||||
{
|
||||
if (m_useTemporaryTable)
|
||||
m_sqlStatementBuilder.bind("$temporary", "TEMPORARY ");
|
||||
else
|
||||
m_sqlStatementBuilder.bindEmptyText("$temporary");
|
||||
}
|
||||
|
||||
} // namespace Sqlite
|
||||
|
||||
@@ -35,12 +35,14 @@ class SQLITE_EXPORT CreateTableSqlStatementBuilder
|
||||
public:
|
||||
CreateTableSqlStatementBuilder();
|
||||
|
||||
void setTable(Utils::SmallString &&tableName);
|
||||
void setTableName(Utils::SmallString &&tableName);
|
||||
void addColumn(Utils::SmallString &&columnName,
|
||||
ColumnType columnType,
|
||||
IsPrimaryKey isPrimaryKey = IsPrimaryKey::No);
|
||||
Contraint constraint = Contraint::NoConstraint);
|
||||
void setColumns(const SqliteColumns &columns);
|
||||
void setUseWithoutRowId(bool useWithoutRowId);
|
||||
void setUseIfNotExists(bool useIfNotExists);
|
||||
void setUseTemporaryTable(bool useTemporaryTable);
|
||||
|
||||
void clear();
|
||||
void clearColumns();
|
||||
@@ -52,12 +54,17 @@ public:
|
||||
protected:
|
||||
void bindColumnDefinitions() const;
|
||||
void bindAll() const;
|
||||
void bindWithoutRowId() const;
|
||||
void bindIfNotExists() const;
|
||||
void bindTemporary() const;
|
||||
|
||||
private:
|
||||
mutable SqlStatementBuilder m_sqlStatementBuilder;
|
||||
Utils::SmallString m_tableName;
|
||||
SqliteColumns m_columns;
|
||||
bool m_useWithoutRowId;
|
||||
bool m_useWithoutRowId = false;
|
||||
bool m_useIfNotExits = false;
|
||||
bool m_useTemporaryTable = false;
|
||||
};
|
||||
|
||||
} // namespace Sqlite
|
||||
|
||||
@@ -38,17 +38,17 @@ public:
|
||||
|
||||
SqliteColumn(Utils::SmallString &&name,
|
||||
ColumnType type = ColumnType::Numeric,
|
||||
IsPrimaryKey isPrimaryKey = IsPrimaryKey::No)
|
||||
Contraint constraint = Contraint::NoConstraint)
|
||||
: m_name(std::move(name)),
|
||||
m_type(type),
|
||||
m_isPrimaryKey(isPrimaryKey)
|
||||
m_constraint(constraint)
|
||||
{}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_name.clear();
|
||||
m_type = ColumnType::Numeric;
|
||||
m_isPrimaryKey = IsPrimaryKey::No;
|
||||
m_constraint = Contraint::NoConstraint;
|
||||
}
|
||||
|
||||
void setName(Utils::SmallString &&newName)
|
||||
@@ -71,14 +71,14 @@ public:
|
||||
return m_type;
|
||||
}
|
||||
|
||||
void setIsPrimaryKey(IsPrimaryKey isPrimaryKey)
|
||||
void setContraint(Contraint constraint)
|
||||
{
|
||||
m_isPrimaryKey = isPrimaryKey;
|
||||
m_constraint = constraint;
|
||||
}
|
||||
|
||||
bool isPrimaryKey() const
|
||||
Contraint constraint() const
|
||||
{
|
||||
return m_isPrimaryKey == IsPrimaryKey::Yes;
|
||||
return m_constraint;
|
||||
}
|
||||
|
||||
Utils::SmallString typeString() const
|
||||
@@ -98,13 +98,13 @@ public:
|
||||
{
|
||||
return first.m_name == second.m_name
|
||||
&& first.m_type == second.m_type
|
||||
&& first.m_isPrimaryKey == second.m_isPrimaryKey;
|
||||
&& first.m_constraint == second.m_constraint;
|
||||
}
|
||||
|
||||
private:
|
||||
Utils::SmallString m_name;
|
||||
ColumnType m_type = ColumnType::Numeric;
|
||||
IsPrimaryKey m_isPrimaryKey = IsPrimaryKey::No;
|
||||
Contraint m_constraint = Contraint::NoConstraint;
|
||||
};
|
||||
|
||||
using SqliteColumns = std::vector<SqliteColumn>;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "sqlitedatabase.h"
|
||||
|
||||
#include "sqlitetable.h"
|
||||
#include "sqlitetransaction.h"
|
||||
|
||||
namespace Sqlite {
|
||||
|
||||
@@ -34,6 +35,12 @@ SqliteDatabase::SqliteDatabase()
|
||||
{
|
||||
}
|
||||
|
||||
SqliteDatabase::SqliteDatabase(Utils::PathString &&databaseFilePath)
|
||||
: m_databaseBackend(*this)
|
||||
{
|
||||
open(std::move(databaseFilePath));
|
||||
}
|
||||
|
||||
void SqliteDatabase::open()
|
||||
{
|
||||
m_databaseBackend.open(m_databaseFilePath, m_openMode);
|
||||
@@ -61,7 +68,7 @@ bool SqliteDatabase::isOpen() const
|
||||
|
||||
SqliteTable &SqliteDatabase::addTable()
|
||||
{
|
||||
m_sqliteTables.emplace_back(*this);
|
||||
m_sqliteTables.emplace_back();
|
||||
|
||||
return m_sqliteTables.back();
|
||||
}
|
||||
@@ -118,8 +125,12 @@ void SqliteDatabase::execute(Utils::SmallStringView sqlStatement)
|
||||
|
||||
void SqliteDatabase::initializeTables()
|
||||
{
|
||||
SqliteImmediateTransaction<SqliteDatabase> transaction(*this);
|
||||
|
||||
for (SqliteTable &table : m_sqliteTables)
|
||||
table.initialize();
|
||||
table.initialize(*this);
|
||||
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
SqliteDatabaseBackend &SqliteDatabase::backend()
|
||||
|
||||
@@ -37,12 +37,14 @@ namespace Sqlite {
|
||||
|
||||
class SQLITE_EXPORT SqliteDatabase
|
||||
{
|
||||
template <typename Database>
|
||||
friend class SqliteAbstractTransaction;
|
||||
friend class SqliteStatement;
|
||||
friend class SqliteBackend;
|
||||
|
||||
public:
|
||||
SqliteDatabase();
|
||||
SqliteDatabase(Utils::PathString &&databaseFilePath);
|
||||
|
||||
SqliteDatabase(const SqliteDatabase &) = delete;
|
||||
bool operator=(const SqliteDatabase &) = delete;
|
||||
|
||||
@@ -38,14 +38,6 @@
|
||||
|
||||
#include "sqlite3.h"
|
||||
|
||||
#if defined(Q_OS_DARWIN) && defined(Q_CC_GNU)
|
||||
#define QTC_THREAD_LOCAL __thread
|
||||
#else
|
||||
#define QTC_THREAD_LOCAL thread_local
|
||||
#endif
|
||||
|
||||
#define SIZE_OF_BYTEARRAY_ARRAY(array) sizeof(array)/sizeof(QByteArray)
|
||||
|
||||
namespace Sqlite {
|
||||
|
||||
SqliteDatabaseBackend::SqliteDatabaseBackend(SqliteDatabase &database)
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
# define SQLITE_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
namespace Sqlite {
|
||||
|
||||
enum class ColumnType : char
|
||||
{
|
||||
Numeric,
|
||||
@@ -46,10 +48,11 @@ enum class ColumnType : char
|
||||
None
|
||||
};
|
||||
|
||||
enum class IsPrimaryKey : char
|
||||
enum class Contraint : char
|
||||
{
|
||||
No,
|
||||
Yes
|
||||
NoConstraint,
|
||||
PrimaryKey,
|
||||
Unique
|
||||
};
|
||||
|
||||
enum class ColumnConstraint : char
|
||||
@@ -84,3 +87,5 @@ enum TextEncoding : char
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
} // namespace Sqlite
|
||||
|
||||
@@ -37,6 +37,8 @@ public:
|
||||
using SqliteStatement::next;
|
||||
using SqliteStatement::reset;
|
||||
using SqliteStatement::value;
|
||||
using SqliteStatement::structValues;
|
||||
using SqliteStatement::tupleValues;
|
||||
using SqliteStatement::text;
|
||||
using SqliteStatement::values;
|
||||
using SqliteStatement::columnCount;
|
||||
|
||||
@@ -48,6 +48,8 @@ public:
|
||||
using SqliteStatement::value;
|
||||
using SqliteStatement::text;
|
||||
using SqliteStatement::values;
|
||||
using SqliteStatement::structValues;
|
||||
using SqliteStatement::tupleValues;
|
||||
using SqliteStatement::columnCount;
|
||||
using SqliteStatement::columnNames;
|
||||
using SqliteStatement::toValue;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -31,8 +31,12 @@
|
||||
|
||||
#include <utils/smallstringvector.h>
|
||||
|
||||
#include <type_traits>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <tuple>
|
||||
|
||||
using std::int64_t;
|
||||
|
||||
struct sqlite3_stmt;
|
||||
struct sqlite3;
|
||||
@@ -61,31 +65,45 @@ protected:
|
||||
Utils::SmallStringVector columnNames() const;
|
||||
|
||||
void bind(int index, int value);
|
||||
void bind(int index, qint64 value);
|
||||
void bind(int index, long long value);
|
||||
void bind(int index, double value);
|
||||
void bind(int index, Utils::SmallStringView value);
|
||||
|
||||
template<typename ... Values>
|
||||
void bindValues(Values ... values)
|
||||
void bind(int index, uint value)
|
||||
{
|
||||
bind(index, static_cast<long long>(value));
|
||||
}
|
||||
|
||||
void bind(int index, long value)
|
||||
{
|
||||
bind(index, static_cast<long long>(value));
|
||||
}
|
||||
|
||||
void bindValues()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename... Values>
|
||||
void bindValues(Values... values)
|
||||
{
|
||||
bindValuesByIndex(1, values...);
|
||||
}
|
||||
|
||||
template<typename ... Values>
|
||||
void write(Values ... values)
|
||||
template<typename... Values>
|
||||
void write(Values... values)
|
||||
{
|
||||
bindValuesByIndex(1, values...);
|
||||
execute();
|
||||
}
|
||||
|
||||
template<typename ... Values>
|
||||
void bindNameValues(Values ... values)
|
||||
template<typename... Values>
|
||||
void bindNameValues(Values... values)
|
||||
{
|
||||
bindValuesByName(values...);
|
||||
}
|
||||
|
||||
template<typename ... Values>
|
||||
void writeNamed(Values ... values)
|
||||
template<typename... Values>
|
||||
void writeNamed(Values... values)
|
||||
{
|
||||
bindValuesByName(values...);
|
||||
execute();
|
||||
@@ -99,11 +117,231 @@ protected:
|
||||
void setBindingColumnNames(const Utils::SmallStringVector &bindingColumnNames);
|
||||
const Utils::SmallStringVector &bindingColumnNames() const;
|
||||
|
||||
template <typename ContainerType>
|
||||
ContainerType values(const std::vector<int> &columns, int size = 0) const;
|
||||
template <typename... ResultType>
|
||||
std::vector<std::tuple<ResultType...>> tupleValues(std::size_t reserveSize)
|
||||
{
|
||||
using Container = std::vector<std::tuple<ResultType...>>;
|
||||
Container resultValues;
|
||||
resultValues.reserve(reserveSize);
|
||||
|
||||
template <typename ContainerType>
|
||||
ContainerType values(int column = 0) const;
|
||||
while (next())
|
||||
emplaceTupleValues<Container, ResultType...>(resultValues);
|
||||
|
||||
reset();
|
||||
|
||||
return resultValues;
|
||||
}
|
||||
|
||||
template <typename... ResultType,
|
||||
typename... QueryType>
|
||||
std::vector<std::tuple<ResultType...>> tupleValues(std::size_t reserveSize, const QueryType&... queryValues)
|
||||
{
|
||||
using Container = std::vector<std::tuple<ResultType...>>;
|
||||
Container resultValues;
|
||||
resultValues.reserve(reserveSize);
|
||||
|
||||
bindValues(queryValues...);
|
||||
|
||||
while (next())
|
||||
emplaceTupleValues<Container, ResultType...>(resultValues);
|
||||
|
||||
reset();
|
||||
|
||||
return resultValues;
|
||||
}
|
||||
|
||||
template <typename... ResultType,
|
||||
typename... ElementType>
|
||||
std::vector<std::tuple<ResultType...>> tupleValues(std::size_t reserveSize,
|
||||
const std::vector<std::tuple<ElementType...>> &queryTuples)
|
||||
{
|
||||
using Container = std::vector<std::tuple<ResultType...>>;
|
||||
Container resultValues;
|
||||
resultValues.reserve(reserveSize);
|
||||
|
||||
for (const auto &queryTuple : queryTuples) {
|
||||
bindTupleValues(queryTuple);
|
||||
|
||||
while (next())
|
||||
emplaceTupleValues<Container, ResultType...>(resultValues);
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
return resultValues;
|
||||
}
|
||||
|
||||
template <typename... ResultType,
|
||||
typename QueryElementType>
|
||||
std::vector<std::tuple<ResultType...>> tupleValues(std::size_t reserveSize,
|
||||
const std::vector<QueryElementType> &queryValues)
|
||||
{
|
||||
using Container = std::vector<std::tuple<ResultType...>>;
|
||||
Container resultValues;
|
||||
resultValues.reserve(reserveSize);
|
||||
|
||||
for (const QueryElementType &queryValue : queryValues) {
|
||||
bindValues(queryValue);
|
||||
|
||||
while (next())
|
||||
emplaceTupleValues<Container, ResultType...>(resultValues);
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
return resultValues;
|
||||
}
|
||||
|
||||
template <typename ResultType,
|
||||
typename... ResultEntryType>
|
||||
std::vector<ResultType> structValues(std::size_t reserveSize)
|
||||
{
|
||||
using Container = std::vector<ResultType>;
|
||||
Container resultValues;
|
||||
resultValues.reserve(reserveSize);
|
||||
|
||||
while (next())
|
||||
pushBackStructValues<Container, ResultEntryType...>(resultValues);
|
||||
|
||||
reset();
|
||||
|
||||
return resultValues;
|
||||
}
|
||||
|
||||
template <typename ResultType,
|
||||
typename... ResultEntryType,
|
||||
typename... QueryType>
|
||||
std::vector<ResultType> structValues(std::size_t reserveSize, const QueryType&... queryValues)
|
||||
{
|
||||
using Container = std::vector<ResultType>;
|
||||
Container resultValues;
|
||||
resultValues.reserve(reserveSize);
|
||||
|
||||
bindValues(queryValues...);
|
||||
|
||||
while (next())
|
||||
pushBackStructValues<Container, ResultEntryType...>(resultValues);
|
||||
|
||||
reset();
|
||||
|
||||
return resultValues;
|
||||
}
|
||||
|
||||
template <typename ResultType,
|
||||
typename... ResultEntryType,
|
||||
typename QueryElementType>
|
||||
std::vector<ResultType> structValues(std::size_t reserveSize,
|
||||
const std::vector<QueryElementType> &queryValues)
|
||||
{
|
||||
using Container = std::vector<ResultType>;
|
||||
Container resultValues;
|
||||
resultValues.reserve(reserveSize);
|
||||
|
||||
for (const QueryElementType &queryValue : queryValues) {
|
||||
bindValues(queryValue);
|
||||
|
||||
while (next())
|
||||
pushBackStructValues<Container, ResultEntryType...>(resultValues);
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
return resultValues;
|
||||
}
|
||||
|
||||
template <typename ResultType,
|
||||
typename... ResultEntryType,
|
||||
typename... QueryElementType>
|
||||
std::vector<ResultType> structValues(std::size_t reserveSize,
|
||||
const std::vector<std::tuple<QueryElementType...>> &queryTuples)
|
||||
{
|
||||
using Container = std::vector<ResultType>;
|
||||
Container resultValues;
|
||||
resultValues.reserve(reserveSize);
|
||||
|
||||
for (const auto &queryTuple : queryTuples) {
|
||||
bindTupleValues(queryTuple);
|
||||
|
||||
while (next())
|
||||
pushBackStructValues<Container, ResultEntryType...>(resultValues);
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
return resultValues;
|
||||
}
|
||||
|
||||
template <typename ResultType,
|
||||
typename... ElementType>
|
||||
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));
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
return resultValues;
|
||||
}
|
||||
|
||||
template <typename ResultType,
|
||||
typename... QueryType>
|
||||
std::vector<ResultType> values(std::size_t reserveSize, const QueryType&... queryValues)
|
||||
{
|
||||
std::vector<ResultType> resultValues;
|
||||
resultValues.reserve(reserveSize);
|
||||
|
||||
bindValues(queryValues...);
|
||||
|
||||
while (next())
|
||||
resultValues.push_back(value<ResultType>(0));
|
||||
|
||||
reset();
|
||||
|
||||
return resultValues;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
static Type toValue(Utils::SmallStringView sqlStatement, SqliteDatabase &database);
|
||||
@@ -141,14 +379,45 @@ protected:
|
||||
SqliteDatabaseBackend &databaseBackend);
|
||||
|
||||
private:
|
||||
template <typename Container,
|
||||
typename... ResultType,
|
||||
int... Index>
|
||||
void emplaceTupleValues(Container &container, std::integer_sequence<int, Index...>)
|
||||
{
|
||||
container.emplace_back(value<ResultType>(Index)...);
|
||||
}
|
||||
|
||||
template <typename Container,
|
||||
typename... ResultType>
|
||||
void emplaceTupleValues(Container &container)
|
||||
{
|
||||
emplaceTupleValues<Container, ResultType...>(container, std::make_integer_sequence<int, sizeof...(ResultType)>{});
|
||||
}
|
||||
|
||||
template <typename Container,
|
||||
typename... ResultEntryType,
|
||||
int... Index>
|
||||
void pushBackStructValues(Container &container, std::integer_sequence<int, Index...>)
|
||||
{
|
||||
using ResultType = typename Container::value_type;
|
||||
container.push_back(ResultType{value<ResultEntryType>(Index)...});
|
||||
}
|
||||
|
||||
template <typename Container,
|
||||
typename... ResultEntryType>
|
||||
void pushBackStructValues(Container &container)
|
||||
{
|
||||
pushBackStructValues<Container, ResultEntryType...>(container, std::make_integer_sequence<int, sizeof...(ResultEntryType)>{});
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
void bindValuesByIndex(int index, Type value)
|
||||
{
|
||||
bind(index, value);
|
||||
}
|
||||
|
||||
template<typename Type, typename ... Value>
|
||||
void bindValuesByIndex(int index, Type value, Value ... values)
|
||||
template<typename Type, typename... Value>
|
||||
void bindValuesByIndex(int index, Type value, Value... values)
|
||||
{
|
||||
bind(index, value);
|
||||
bindValuesByIndex(index + 1, values...);
|
||||
@@ -160,13 +429,26 @@ private:
|
||||
bind(bindingIndexForName(name), value);
|
||||
}
|
||||
|
||||
template<typename Type, typename ... Values>
|
||||
void bindValuesByName(Utils::SmallStringView name, Type value, Values ... values)
|
||||
template<typename Type, typename... Values>
|
||||
void bindValuesByName(Utils::SmallStringView name, Type value, Values... values)
|
||||
{
|
||||
bind(bindingIndexForName(name), value);
|
||||
bindValuesByName(values...);
|
||||
}
|
||||
|
||||
template <typename TupleType, std::size_t... Index>
|
||||
void bindTupleValuesElement(const TupleType &tuple, std::index_sequence<Index...>)
|
||||
{
|
||||
bindValues(std::get<Index>(tuple)...);
|
||||
}
|
||||
|
||||
template <typename TupleType,
|
||||
typename Indices = std::make_index_sequence<std::tuple_size<TupleType>::value>>
|
||||
void bindTupleValues(const TupleType &element)
|
||||
{
|
||||
bindTupleValuesElement(element, Indices());
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<sqlite3_stmt, void (*)(sqlite3_stmt*)> m_compiledStatement;
|
||||
Utils::SmallStringVector m_bindingColumnNames;
|
||||
@@ -176,4 +458,21 @@ private:
|
||||
mutable bool m_isReadyToFetchValues;
|
||||
};
|
||||
|
||||
extern template SQLITE_EXPORT void SqliteStatement::bind(Utils::SmallStringView name, int value);
|
||||
extern template SQLITE_EXPORT void SqliteStatement::bind(Utils::SmallStringView name, long value);
|
||||
extern template SQLITE_EXPORT void SqliteStatement::bind(Utils::SmallStringView name, long long value);
|
||||
extern template SQLITE_EXPORT void SqliteStatement::bind(Utils::SmallStringView name, double value);
|
||||
extern template SQLITE_EXPORT void SqliteStatement::bind(Utils::SmallStringView name, Utils::SmallStringView text);
|
||||
|
||||
extern template SQLITE_EXPORT int SqliteStatement::toValue<int>(Utils::SmallStringView sqlStatement, SqliteDatabase &database);
|
||||
extern template SQLITE_EXPORT long long SqliteStatement::toValue<long long>(Utils::SmallStringView sqlStatement, SqliteDatabase &database);
|
||||
extern template SQLITE_EXPORT double SqliteStatement::toValue<double>(Utils::SmallStringView sqlStatement, SqliteDatabase &database);
|
||||
extern template SQLITE_EXPORT Utils::SmallString SqliteStatement::toValue<Utils::SmallString>(Utils::SmallStringView sqlStatement, SqliteDatabase &database);
|
||||
|
||||
template <> SQLITE_EXPORT int SqliteStatement::value<int>(int column) const;
|
||||
template <> SQLITE_EXPORT long SqliteStatement::value<long>(int column) const;
|
||||
template <> SQLITE_EXPORT long long SqliteStatement::value<long long>(int column) const;
|
||||
template <> SQLITE_EXPORT double SqliteStatement::value<double>(int column) const;
|
||||
extern template SQLITE_EXPORT Utils::SmallString SqliteStatement::value<Utils::SmallString>(int column) const;
|
||||
extern template SQLITE_EXPORT Utils::PathString SqliteStatement::value<Utils::PathString>(int column) const;
|
||||
} // namespace Sqlite
|
||||
|
||||
@@ -25,32 +25,8 @@
|
||||
|
||||
#include "sqlitetable.h"
|
||||
|
||||
#include "sqlitecolumn.h"
|
||||
#include "sqlitedatabase.h"
|
||||
#include "createtablesqlstatementbuilder.h"
|
||||
#include "sqlitewritestatement.h"
|
||||
#include "sqlitetransaction.h"
|
||||
|
||||
namespace Sqlite {
|
||||
|
||||
void SqliteTable::initialize()
|
||||
{
|
||||
try {
|
||||
CreateTableSqlStatementBuilder createTableSqlStatementBuilder;
|
||||
|
||||
createTableSqlStatementBuilder.setTable(m_tableName.clone());
|
||||
createTableSqlStatementBuilder.setUseWithoutRowId(m_withoutRowId);
|
||||
createTableSqlStatementBuilder.setColumns(m_sqliteColumns);
|
||||
|
||||
SqliteImmediateTransaction transaction(m_sqliteDatabase);
|
||||
m_sqliteDatabase.execute(createTableSqlStatementBuilder.sqlStatement());
|
||||
transaction.commit();
|
||||
|
||||
m_isReady = true;
|
||||
|
||||
} catch (const SqliteException &exception) {
|
||||
exception.printWarning();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Sqlite
|
||||
|
||||
@@ -25,8 +25,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "createtablesqlstatementbuilder.h"
|
||||
#include "sqliteglobal.h"
|
||||
#include "sqlitecolumn.h"
|
||||
#include "sqliteexception.h"
|
||||
|
||||
namespace Sqlite {
|
||||
|
||||
@@ -35,11 +37,6 @@ class SqliteDatabase;
|
||||
class SqliteTable
|
||||
{
|
||||
public:
|
||||
SqliteTable(SqliteDatabase &m_sqliteDatabase)
|
||||
: m_sqliteDatabase(m_sqliteDatabase)
|
||||
{
|
||||
}
|
||||
|
||||
void setName(Utils::SmallString &&name)
|
||||
{
|
||||
m_tableName = std::move(name);
|
||||
@@ -60,11 +57,16 @@ public:
|
||||
return m_withoutRowId;
|
||||
}
|
||||
|
||||
void setUseIfNotExists(bool useIfNotExists)
|
||||
{
|
||||
m_useIfNotExists = useIfNotExists;
|
||||
}
|
||||
|
||||
SqliteColumn &addColumn(Utils::SmallString &&name,
|
||||
ColumnType type = ColumnType::Numeric,
|
||||
IsPrimaryKey isPrimaryKey = IsPrimaryKey::No)
|
||||
Contraint constraint = Contraint::NoConstraint)
|
||||
{
|
||||
m_sqliteColumns.emplace_back(std::move(name), type, isPrimaryKey);
|
||||
m_sqliteColumns.emplace_back(std::move(name), type, constraint);
|
||||
|
||||
return m_sqliteColumns.back();
|
||||
}
|
||||
@@ -79,13 +81,31 @@ public:
|
||||
return m_isReady;
|
||||
}
|
||||
|
||||
void initialize();
|
||||
template <typename Database>
|
||||
void initialize(Database &database)
|
||||
{
|
||||
try {
|
||||
CreateTableSqlStatementBuilder builder;
|
||||
|
||||
builder.setTableName(m_tableName.clone());
|
||||
builder.setUseWithoutRowId(m_withoutRowId);
|
||||
builder.setUseIfNotExists(m_useIfNotExists);
|
||||
builder.setColumns(m_sqliteColumns);
|
||||
|
||||
database.execute(builder.sqlStatement());
|
||||
|
||||
m_isReady = true;
|
||||
|
||||
} catch (const SqliteException &exception) {
|
||||
exception.printWarning();
|
||||
}
|
||||
}
|
||||
|
||||
friend bool operator==(const SqliteTable &first, const SqliteTable &second)
|
||||
{
|
||||
return first.m_tableName == second.m_tableName
|
||||
&& &first.m_sqliteDatabase == &second.m_sqliteDatabase
|
||||
&& first.m_withoutRowId == second.m_withoutRowId
|
||||
&& first.m_useIfNotExists == second.m_useIfNotExists
|
||||
&& first.m_isReady == second.m_isReady
|
||||
&& first.m_sqliteColumns == second.m_sqliteColumns;
|
||||
}
|
||||
@@ -93,8 +113,8 @@ public:
|
||||
private:
|
||||
Utils::SmallString m_tableName;
|
||||
SqliteColumns m_sqliteColumns;
|
||||
SqliteDatabase &m_sqliteDatabase;
|
||||
bool m_withoutRowId = false;
|
||||
bool m_useIfNotExists = false;
|
||||
bool m_isReady = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -31,44 +31,4 @@
|
||||
|
||||
namespace Sqlite {
|
||||
|
||||
SqliteAbstractTransaction::~SqliteAbstractTransaction()
|
||||
{
|
||||
if (!m_isAlreadyCommited)
|
||||
m_databaseBackend.execute("ROLLBACK");
|
||||
}
|
||||
|
||||
void SqliteAbstractTransaction::commit()
|
||||
{
|
||||
m_databaseBackend.execute("COMMIT");
|
||||
m_isAlreadyCommited = true;
|
||||
}
|
||||
|
||||
SqliteAbstractTransaction::SqliteAbstractTransaction(SqliteDatabaseBackend &backend)
|
||||
: m_databaseBackend(backend)
|
||||
{
|
||||
}
|
||||
|
||||
SqliteAbstractTransaction::SqliteAbstractTransaction(SqliteDatabase &database)
|
||||
: SqliteAbstractTransaction(database.backend())
|
||||
{
|
||||
}
|
||||
|
||||
SqliteTransaction::SqliteTransaction(SqliteDatabase &database)
|
||||
: SqliteAbstractTransaction(database)
|
||||
{
|
||||
m_databaseBackend.execute("BEGIN");
|
||||
}
|
||||
|
||||
SqliteImmediateTransaction::SqliteImmediateTransaction(SqliteDatabase &database)
|
||||
: SqliteAbstractTransaction(database)
|
||||
{
|
||||
m_databaseBackend.execute("BEGIN IMMEDIATE");
|
||||
}
|
||||
|
||||
SqliteExclusiveTransaction::SqliteExclusiveTransaction(SqliteDatabase &database)
|
||||
: SqliteAbstractTransaction(database)
|
||||
{
|
||||
m_databaseBackend.execute("BEGIN EXCLUSIVE");
|
||||
}
|
||||
|
||||
} // namespace Sqlite
|
||||
|
||||
@@ -32,43 +32,66 @@ namespace Sqlite {
|
||||
class SqliteDatabaseBackend;
|
||||
class SqliteDatabase;
|
||||
|
||||
class SQLITE_EXPORT SqliteAbstractTransaction
|
||||
template <typename Database>
|
||||
class SqliteAbstractTransaction
|
||||
{
|
||||
public:
|
||||
virtual ~SqliteAbstractTransaction();
|
||||
virtual ~SqliteAbstractTransaction()
|
||||
{
|
||||
if (!m_isAlreadyCommited)
|
||||
m_database.execute("ROLLBACK");
|
||||
}
|
||||
|
||||
void commit();
|
||||
void commit()
|
||||
{
|
||||
m_database.execute("COMMIT");
|
||||
m_isAlreadyCommited = true;
|
||||
}
|
||||
|
||||
protected:
|
||||
SqliteAbstractTransaction(SqliteDatabaseBackend &backend);
|
||||
SqliteAbstractTransaction(SqliteDatabase &database);
|
||||
|
||||
protected:
|
||||
SqliteDatabaseBackend &m_databaseBackend;
|
||||
SqliteAbstractTransaction(Database &database)
|
||||
: m_database(database)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
Database &m_database;
|
||||
bool m_isAlreadyCommited = false;
|
||||
};
|
||||
|
||||
|
||||
class SQLITE_EXPORT SqliteTransaction final : public SqliteAbstractTransaction
|
||||
template <typename Database>
|
||||
class SqliteTransaction final : public SqliteAbstractTransaction<Database>
|
||||
{
|
||||
public:
|
||||
SqliteTransaction(SqliteDatabase &database);
|
||||
SqliteTransaction(Database &database)
|
||||
: SqliteAbstractTransaction<Database>(database)
|
||||
{
|
||||
database.execute("BEGIN");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class SQLITE_EXPORT SqliteImmediateTransaction final : public SqliteAbstractTransaction
|
||||
template <typename Database>
|
||||
class SqliteImmediateTransaction final : public SqliteAbstractTransaction<Database>
|
||||
{
|
||||
public:
|
||||
SqliteImmediateTransaction(SqliteDatabase &database);
|
||||
SqliteImmediateTransaction(Database &database)
|
||||
: SqliteAbstractTransaction<Database>(database)
|
||||
{
|
||||
database.execute("BEGIN IMMEDIATE");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class SQLITE_EXPORT SqliteExclusiveTransaction final : public SqliteAbstractTransaction
|
||||
template <typename Database>
|
||||
class SqliteExclusiveTransaction final : public SqliteAbstractTransaction<Database>
|
||||
{
|
||||
public:
|
||||
SqliteExclusiveTransaction(SqliteDatabase &database);
|
||||
SqliteExclusiveTransaction(Database &database)
|
||||
: SqliteAbstractTransaction<Database>(database)
|
||||
{
|
||||
database.execute("BEGIN EXCLUSIVE");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
namespace Sqlite {
|
||||
|
||||
SqlStatementBuilder::SqlStatementBuilder(Utils::SmallString &&sqlTemplate)
|
||||
SqlStatementBuilder::SqlStatementBuilder(Utils::SmallStringView sqlTemplate)
|
||||
: m_sqlTemplate(std::move(sqlTemplate))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ class SQLITE_EXPORT SqlStatementBuilder
|
||||
{
|
||||
using BindingPair = std::pair<Utils::SmallString, Utils::SmallString>;
|
||||
public:
|
||||
SqlStatementBuilder(Utils::SmallString &&m_sqlTemplate);
|
||||
SqlStatementBuilder(Utils::SmallStringView m_sqlTemplate);
|
||||
|
||||
void bindEmptyText(Utils::SmallString &&name);
|
||||
void bind(Utils::SmallString &&name, Utils::SmallString &&text);
|
||||
@@ -79,8 +79,8 @@ protected:
|
||||
Q_NORETURN static void throwException(const char *whatHasHappened, const char *errorMessage);
|
||||
|
||||
private:
|
||||
Utils::SmallString m_sqlTemplate;
|
||||
mutable Utils::SmallString m_sqlStatement;
|
||||
Utils::BasicSmallString<510> m_sqlTemplate;
|
||||
mutable Utils::BasicSmallString<510> m_sqlStatement;
|
||||
mutable std::vector<BindingPair> m_bindings;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user