aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/sqlite
diff options
context:
space:
mode:
authorMarco Bubke <[email protected]>2017-08-17 15:33:25 +0200
committerMarco Bubke <[email protected]>2017-08-28 14:50:33 +0000
commit1a25b61576f82f4042cf57ad0c51a94bedbed77c (patch)
treedb26c7bb8cd49530b71a895f3e4cb2c37b5f29d4 /src/libs/sqlite
parent8617f497bcb0c30ea83ef5afe1e40e8b5d3802b4 (diff)
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 <[email protected]>
Diffstat (limited to 'src/libs/sqlite')
-rw-r--r--src/libs/sqlite/createtablesqlstatementbuilder.cpp48
-rw-r--r--src/libs/sqlite/createtablesqlstatementbuilder.h13
-rw-r--r--src/libs/sqlite/sqlitecolumn.h18
-rw-r--r--src/libs/sqlite/sqlitedatabase.cpp15
-rw-r--r--src/libs/sqlite/sqlitedatabase.h2
-rw-r--r--src/libs/sqlite/sqlitedatabasebackend.cpp8
-rw-r--r--src/libs/sqlite/sqliteglobal.h11
-rw-r--r--src/libs/sqlite/sqlitereadstatement.h2
-rw-r--r--src/libs/sqlite/sqlitereadwritestatement.h2
-rw-r--r--src/libs/sqlite/sqlitestatement.cpp109
-rw-r--r--src/libs/sqlite/sqlitestatement.h335
-rw-r--r--src/libs/sqlite/sqlitetable.cpp24
-rw-r--r--src/libs/sqlite/sqlitetable.h40
-rw-r--r--src/libs/sqlite/sqlitetransaction.cpp40
-rw-r--r--src/libs/sqlite/sqlitetransaction.h55
-rw-r--r--src/libs/sqlite/sqlstatementbuilder.cpp2
-rw-r--r--src/libs/sqlite/sqlstatementbuilder.h6
17 files changed, 516 insertions, 214 deletions
diff --git a/src/libs/sqlite/createtablesqlstatementbuilder.cpp b/src/libs/sqlite/createtablesqlstatementbuilder.cpp
index c543d28de39..dfdc779faad 100644
--- a/src/libs/sqlite/createtablesqlstatementbuilder.cpp
+++ b/src/libs/sqlite/createtablesqlstatementbuilder.cpp
@@ -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
diff --git a/src/libs/sqlite/createtablesqlstatementbuilder.h b/src/libs/sqlite/createtablesqlstatementbuilder.h
index f33a8920a23..00c9ebd45a1 100644
--- a/src/libs/sqlite/createtablesqlstatementbuilder.h
+++ b/src/libs/sqlite/createtablesqlstatementbuilder.h
@@ -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
diff --git a/src/libs/sqlite/sqlitecolumn.h b/src/libs/sqlite/sqlitecolumn.h
index c16333ce231..e25ee68b2d7 100644
--- a/src/libs/sqlite/sqlitecolumn.h
+++ b/src/libs/sqlite/sqlitecolumn.h
@@ -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>;
diff --git a/src/libs/sqlite/sqlitedatabase.cpp b/src/libs/sqlite/sqlitedatabase.cpp
index ec2379c61c1..4d53eecb35a 100644
--- a/src/libs/sqlite/sqlitedatabase.cpp
+++ b/src/libs/sqlite/sqlitedatabase.cpp
@@ -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()
diff --git a/src/libs/sqlite/sqlitedatabase.h b/src/libs/sqlite/sqlitedatabase.h
index 2e178a0190c..0ac340bb129 100644
--- a/src/libs/sqlite/sqlitedatabase.h
+++ b/src/libs/sqlite/sqlitedatabase.h
@@ -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;
diff --git a/src/libs/sqlite/sqlitedatabasebackend.cpp b/src/libs/sqlite/sqlitedatabasebackend.cpp
index 79eed32eab4..6ea70f30ada 100644
--- a/src/libs/sqlite/sqlitedatabasebackend.cpp
+++ b/src/libs/sqlite/sqlitedatabasebackend.cpp
@@ -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)
diff --git a/src/libs/sqlite/sqliteglobal.h b/src/libs/sqlite/sqliteglobal.h
index cb5208df5ff..af9d9ac36c0 100644
--- a/src/libs/sqlite/sqliteglobal.h
+++ b/src/libs/sqlite/sqliteglobal.h
@@ -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
diff --git a/src/libs/sqlite/sqlitereadstatement.h b/src/libs/sqlite/sqlitereadstatement.h
index 55bd5c15fbb..d0c88602811 100644
--- a/src/libs/sqlite/sqlitereadstatement.h
+++ b/src/libs/sqlite/sqlitereadstatement.h
@@ -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;
diff --git a/src/libs/sqlite/sqlitereadwritestatement.h b/src/libs/sqlite/sqlitereadwritestatement.h
index 8f93ff85bed..d53614bcc02 100644
--- a/src/libs/sqlite/sqlitereadwritestatement.h
+++ b/src/libs/sqlite/sqlitereadwritestatement.h
@@ -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;
diff --git a/src/libs/sqlite/sqlitestatement.cpp b/src/libs/sqlite/sqlitestatement.cpp
index fee0130acc7..4c4a458a968 100644
--- a/src/libs/sqlite/sqlitestatement.cpp
+++ b/src/libs/sqlite/sqlitestatement.cpp
@@ -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);
diff --git a/src/libs/sqlite/sqlitestatement.h b/src/libs/sqlite/sqlitestatement.h
index 5f74c267ef3..09c75c16d97 100644
--- a/src/libs/sqlite/sqlitestatement.h
+++ b/src/libs/sqlite/sqlitestatement.h
@@ -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
diff --git a/src/libs/sqlite/sqlitetable.cpp b/src/libs/sqlite/sqlitetable.cpp
index dc987f44772..99b0e95938c 100644
--- a/src/libs/sqlite/sqlitetable.cpp
+++ b/src/libs/sqlite/sqlitetable.cpp
@@ -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
diff --git a/src/libs/sqlite/sqlitetable.h b/src/libs/sqlite/sqlitetable.h
index 62b6b41cb3f..d591f39a59f 100644
--- a/src/libs/sqlite/sqlitetable.h
+++ b/src/libs/sqlite/sqlitetable.h
@@ -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;
};
diff --git a/src/libs/sqlite/sqlitetransaction.cpp b/src/libs/sqlite/sqlitetransaction.cpp
index dd790ee5529..2ee17131c25 100644
--- a/src/libs/sqlite/sqlitetransaction.cpp
+++ b/src/libs/sqlite/sqlitetransaction.cpp
@@ -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
diff --git a/src/libs/sqlite/sqlitetransaction.h b/src/libs/sqlite/sqlitetransaction.h
index 994fbe2b1f5..373b33fd8a9 100644
--- a/src/libs/sqlite/sqlitetransaction.h
+++ b/src/libs/sqlite/sqlitetransaction.h
@@ -32,43 +32,66 @@ namespace Sqlite {
class SqliteDatabaseBackend;
class SqliteDatabase;
-class SQLITE_EXPORT SqliteAbstractTransaction
+template <typename Database>
+class SqliteAbstractTransaction
{
public:
- virtual ~SqliteAbstractTransaction();
-
- void commit();
-
-protected:
- SqliteAbstractTransaction(SqliteDatabaseBackend &backend);
- SqliteAbstractTransaction(SqliteDatabase &database);
+ virtual ~SqliteAbstractTransaction()
+ {
+ if (!m_isAlreadyCommited)
+ m_database.execute("ROLLBACK");
+ }
+
+ void commit()
+ {
+ m_database.execute("COMMIT");
+ m_isAlreadyCommited = true;
+ }
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");
+ }
};
diff --git a/src/libs/sqlite/sqlstatementbuilder.cpp b/src/libs/sqlite/sqlstatementbuilder.cpp
index 4104d8c1f0c..cfa08a2b7b3 100644
--- a/src/libs/sqlite/sqlstatementbuilder.cpp
+++ b/src/libs/sqlite/sqlstatementbuilder.cpp
@@ -33,7 +33,7 @@
namespace Sqlite {
-SqlStatementBuilder::SqlStatementBuilder(Utils::SmallString &&sqlTemplate)
+SqlStatementBuilder::SqlStatementBuilder(Utils::SmallStringView sqlTemplate)
: m_sqlTemplate(std::move(sqlTemplate))
{
}
diff --git a/src/libs/sqlite/sqlstatementbuilder.h b/src/libs/sqlite/sqlstatementbuilder.h
index c24e0b9ed94..670455dc41a 100644
--- a/src/libs/sqlite/sqlstatementbuilder.h
+++ b/src/libs/sqlite/sqlstatementbuilder.h
@@ -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;
};