Clang: Add file cache

The database is using file path integer ids to handle file paths because
otherwise we would save many redundant data. This patch is improving it
further with the introduction of a database based file path cache. The
entries are now divided in a directory path and file name. This is quite
handy for directory based file watching.

Change-Id: I03f2e388e43f3d521d6bf8e39dfb95eb2309dc73
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2017-09-21 11:43:59 +02:00
committed by Tim Jenssen
parent 0be8240002
commit d2e15e5f1e
135 changed files with 3458 additions and 1517 deletions

View File

@@ -17,7 +17,6 @@ SOURCES += \
$$PWD/sqliteglobal.cpp \
$$PWD/sqlitereadstatement.cpp \
$$PWD/sqlitereadwritestatement.cpp \
$$PWD/sqlitestatement.cpp \
$$PWD/sqlitetransaction.cpp \
$$PWD/sqlitewritestatement.cpp \
$$PWD/sqlstatementbuilder.cpp \
@@ -26,7 +25,8 @@ SOURCES += \
$$PWD/utf8stringvector.cpp \
$$PWD/sqlitedatabase.cpp \
$$PWD/sqlitetable.cpp \
$$PWD/sqlitecolumn.cpp
$$PWD/sqlitecolumn.cpp \
$$PWD/sqlitebasestatement.cpp
HEADERS += \
$$PWD/createtablesqlstatementbuilder.h \
$$PWD/sqlitedatabasebackend.h \
@@ -34,7 +34,6 @@ HEADERS += \
$$PWD/sqliteglobal.h \
$$PWD/sqlitereadstatement.h \
$$PWD/sqlitereadwritestatement.h \
$$PWD/sqlitestatement.h \
$$PWD/sqlitetransaction.h \
$$PWD/sqlitewritestatement.h \
$$PWD/sqlstatementbuilder.h \
@@ -44,7 +43,8 @@ HEADERS += \
$$PWD/sqlitedatabase.h \
$$PWD/sqlitetable.h \
$$PWD/sqlitecolumn.h \
$$PWD/sqliteindex.h
$$PWD/sqliteindex.h \
$$PWD/sqlitebasestatement.h
DEFINES += SQLITE_THREADSAFE=2 SQLITE_ENABLE_FTS4 SQLITE_ENABLE_FTS3_PARENTHESIS SQLITE_ENABLE_UNLOCK_NOTIFY SQLITE_ENABLE_COLUMN_METADATA

View File

@@ -23,7 +23,7 @@
**
****************************************************************************/
#include "sqlitestatement.h"
#include "sqlitebasestatement.h"
#include "sqlitedatabase.h"
#include "sqlitedatabasebackend.h"
@@ -40,7 +40,7 @@
namespace Sqlite {
Statement::Statement(Utils::SmallStringView sqlStatement, Database &database)
BaseStatement::BaseStatement(Utils::SmallStringView sqlStatement, Database &database)
: m_compiledStatement(nullptr, deleteCompiledStatement),
m_database(database),
m_bindingParameterCount(0),
@@ -49,11 +49,10 @@ Statement::Statement(Utils::SmallStringView sqlStatement, Database &database)
{
prepare(sqlStatement);
setBindingParameterCount();
setBindingColumnNamesFromStatement();
setColumnCount();
}
void Statement::deleteCompiledStatement(sqlite3_stmt *compiledStatement)
void BaseStatement::deleteCompiledStatement(sqlite3_stmt *compiledStatement)
{
if (compiledStatement)
sqlite3_finalize(compiledStatement);
@@ -92,7 +91,7 @@ private:
std::mutex m_mutex;
};
void Statement::waitForUnlockNotify() const
void BaseStatement::waitForUnlockNotify() const
{
UnlockNotification unlockNotification;
int resultCode = sqlite3_unlock_notify(sqliteDatabaseHandle(),
@@ -105,7 +104,7 @@ void Statement::waitForUnlockNotify() const
unlockNotification.wait();
}
void Statement::reset() const
void BaseStatement::reset() const
{
int resultCode = sqlite3_reset(m_compiledStatement.get());
switch (resultCode) {
@@ -119,7 +118,7 @@ void Statement::reset() const
m_isReadyToFetchValues = false;
}
bool Statement::next() const
bool BaseStatement::next() const
{
int resultCode;
@@ -137,26 +136,26 @@ bool Statement::next() const
return checkForStepError(resultCode);
}
void Statement::step() const
void BaseStatement::step() const
{
next();
}
void Statement::execute() const
void BaseStatement::execute() const
{
next();
reset();
}
int Statement::columnCount() const
int BaseStatement::columnCount() const
{
return m_columnCount;
}
Utils::SmallStringVector Statement::columnNames() const
Utils::SmallStringVector BaseStatement::columnNames() const
{
Utils::SmallStringVector columnNames;
int columnCount = Statement::columnCount();
int columnCount = BaseStatement::columnCount();
columnNames.reserve(std::size_t(columnCount));
for (int columnIndex = 0; columnIndex < columnCount; columnIndex++)
columnNames.emplace_back(sqlite3_column_origin_name(m_compiledStatement.get(), columnIndex));
@@ -164,25 +163,25 @@ Utils::SmallStringVector Statement::columnNames() const
return columnNames;
}
void Statement::bind(int index, int value)
void BaseStatement::bind(int index, int value)
{
int resultCode = sqlite3_bind_int(m_compiledStatement.get(), index, value);
checkForBindingError(resultCode);
}
void Statement::bind(int index, long long value)
void BaseStatement::bind(int index, long long value)
{
int resultCode = sqlite3_bind_int64(m_compiledStatement.get(), index, value);
checkForBindingError(resultCode);
}
void Statement::bind(int index, double value)
void BaseStatement::bind(int index, double value)
{
int resultCode = sqlite3_bind_double(m_compiledStatement.get(), index, value);
checkForBindingError(resultCode);
}
void Statement::bind(int index, Utils::SmallStringView text)
void BaseStatement::bind(int index, Utils::SmallStringView text)
{
int resultCode = sqlite3_bind_text(m_compiledStatement.get(),
index,
@@ -193,35 +192,25 @@ void Statement::bind(int index, Utils::SmallStringView text)
}
template <typename Type>
void Statement::bind(Utils::SmallStringView name, Type value)
void BaseStatement::bind(Utils::SmallStringView name, Type value)
{
int index = bindingIndexForName(name);
checkBindingName(index);
bind(index, value);
}
template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, int value);
template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, long value);
template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, long long value);
template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, double value);
template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, Utils::SmallStringView text);
template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, int value);
template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, long value);
template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, long long value);
template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, double value);
template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, Utils::SmallStringView text);
int Statement::bindingIndexForName(Utils::SmallStringView name) const
int BaseStatement::bindingIndexForName(Utils::SmallStringView name) const
{
return sqlite3_bind_parameter_index(m_compiledStatement.get(), name.data());
}
void Statement::setBindingColumnNames(const Utils::SmallStringVector &bindingColumnNames)
{
m_bindingColumnNames = bindingColumnNames;
}
const Utils::SmallStringVector &Statement::bindingColumnNames() const
{
return m_bindingColumnNames;
}
void Statement::prepare(Utils::SmallStringView sqlStatement)
void BaseStatement::prepare(Utils::SmallStringView sqlStatement)
{
int resultCode;
@@ -242,17 +231,17 @@ void Statement::prepare(Utils::SmallStringView sqlStatement)
checkForPrepareError(resultCode);
}
sqlite3 *Statement::sqliteDatabaseHandle() const
sqlite3 *BaseStatement::sqliteDatabaseHandle() const
{
return m_database.backend().sqliteDatabaseHandle();
}
TextEncoding Statement::databaseTextEncoding()
TextEncoding BaseStatement::databaseTextEncoding()
{
return m_database.backend().textEncoding();
}
bool Statement::checkForStepError(int resultCode) const
bool BaseStatement::checkForStepError(int resultCode) const
{
switch (resultCode) {
case SQLITE_ROW: return true;
@@ -268,7 +257,7 @@ bool Statement::checkForStepError(int resultCode) const
Q_UNREACHABLE();
}
void Statement::checkForPrepareError(int resultCode) const
void BaseStatement::checkForPrepareError(int resultCode) const
{
switch (resultCode) {
case SQLITE_OK: return;
@@ -280,7 +269,7 @@ void Statement::checkForPrepareError(int resultCode) const
throwUnknowError("SqliteStatement::prepareStatement: unknown error has happened");
}
void Statement::checkForBindingError(int resultCode) const
void BaseStatement::checkForBindingError(int resultCode) const
{
switch (resultCode) {
case SQLITE_OK: return;
@@ -292,7 +281,7 @@ void Statement::checkForBindingError(int resultCode) const
throwUnknowError("SqliteStatement::bind: unknown error has happened");
}
void Statement::setIfIsReadyToFetchValues(int resultCode) const
void BaseStatement::setIfIsReadyToFetchValues(int resultCode) const
{
if (resultCode == SQLITE_ROW)
m_isReadyToFetchValues = true;
@@ -301,13 +290,13 @@ void Statement::setIfIsReadyToFetchValues(int resultCode) const
}
void Statement::checkIfIsReadyToFetchValues() const
void BaseStatement::checkIfIsReadyToFetchValues() const
{
if (!m_isReadyToFetchValues)
throwNoValuesToFetch("SqliteStatement::value: there are no values to fetch!");
}
void Statement::checkColumnsAreValid(const std::vector<int> &columns) const
void BaseStatement::checkColumnsAreValid(const std::vector<int> &columns) const
{
for (int column : columns) {
if (column < 0 || column >= m_columnCount)
@@ -315,19 +304,19 @@ void Statement::checkColumnsAreValid(const std::vector<int> &columns) const
}
}
void Statement::checkColumnIsValid(int column) const
void BaseStatement::checkColumnIsValid(int column) const
{
if (column < 0 || column >= m_columnCount)
throwInvalidColumnFetched("SqliteStatement::values: column index out of bound!");
}
void Statement::checkBindingName(int index) const
void BaseStatement::checkBindingName(int index) const
{
if (index <= 0 || index > m_bindingParameterCount)
throwWrongBingingName("SqliteStatement::bind: binding name are not exists in this statement!");
}
void Statement::setBindingParameterCount()
void BaseStatement::setBindingParameterCount()
{
m_bindingParameterCount = sqlite3_bind_parameter_count(m_compiledStatement.get());
}
@@ -340,65 +329,57 @@ Utils::SmallStringView chopFirstLetter(const char *rawBindingName)
return Utils::SmallStringView("");
}
void Statement::setBindingColumnNamesFromStatement()
{
for (int index = 1; index <= m_bindingParameterCount; index++) {
Utils::SmallStringView bindingName = chopFirstLetter(sqlite3_bind_parameter_name(m_compiledStatement.get(), index));
m_bindingColumnNames.push_back(Utils::SmallString(bindingName));
}
}
void Statement::setColumnCount()
void BaseStatement::setColumnCount()
{
m_columnCount = sqlite3_column_count(m_compiledStatement.get());
}
bool Statement::isReadOnlyStatement() const
bool BaseStatement::isReadOnlyStatement() const
{
return sqlite3_stmt_readonly(m_compiledStatement.get());
}
void Statement::throwStatementIsBusy(const char *whatHasHappened) const
void BaseStatement::throwStatementIsBusy(const char *whatHasHappened) const
{
throw StatementIsBusy(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
}
void Statement::throwStatementHasError(const char *whatHasHappened) const
void BaseStatement::throwStatementHasError(const char *whatHasHappened) const
{
throw StatementHasError(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
}
void Statement::throwStatementIsMisused(const char *whatHasHappened) const
void BaseStatement::throwStatementIsMisused(const char *whatHasHappened) const
{
throw StatementIsMisused(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
}
void Statement::throwConstraintPreventsModification(const char *whatHasHappened) const
void BaseStatement::throwConstraintPreventsModification(const char *whatHasHappened) const
{
throw ContraintPreventsModification(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
}
void Statement::throwNoValuesToFetch(const char *whatHasHappened) const
void BaseStatement::throwNoValuesToFetch(const char *whatHasHappened) const
{
throw NoValuesToFetch(whatHasHappened);
}
void Statement::throwInvalidColumnFetched(const char *whatHasHappened) const
void BaseStatement::throwInvalidColumnFetched(const char *whatHasHappened) const
{
throw InvalidColumnFetched(whatHasHappened);
}
void Statement::throwBindingIndexIsOutOfRange(const char *whatHasHappened) const
void BaseStatement::throwBindingIndexIsOutOfRange(const char *whatHasHappened) const
{
throw BindingIndexIsOutOfRange(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
}
void Statement::throwWrongBingingName(const char *whatHasHappened) const
void BaseStatement::throwWrongBingingName(const char *whatHasHappened) const
{
throw WrongBingingName(whatHasHappened);
throw WrongBindingName(whatHasHappened);
}
void Statement::throwUnknowError(const char *whatHasHappened) const
void BaseStatement::throwUnknowError(const char *whatHasHappened) const
{
if (sqliteDatabaseHandle())
throw UnknowError(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
@@ -406,17 +387,17 @@ void Statement::throwUnknowError(const char *whatHasHappened) const
throw UnknowError(whatHasHappened);
}
void Statement::throwBingingTooBig(const char *whatHasHappened) const
void BaseStatement::throwBingingTooBig(const char *whatHasHappened) const
{
throw BindingTooBig(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
}
QString Statement::columnName(int column) const
QString BaseStatement::columnName(int column) const
{
return QString::fromUtf8(sqlite3_column_name(m_compiledStatement.get(), column));
}
Database &Statement::database() const
Database &BaseStatement::database() const
{
return m_database;
}
@@ -445,7 +426,7 @@ static StringType convertToTextForColumn(sqlite3_stmt *sqlStatment, int column)
Q_UNREACHABLE();
}
int Statement::fetchIntValue(int column) const
int BaseStatement::fetchIntValue(int column) const
{
checkIfIsReadyToFetchValues();
checkColumnIsValid(column);
@@ -453,23 +434,23 @@ int Statement::fetchIntValue(int column) const
}
template<>
int Statement::fetchValue<int>(int column) const
int BaseStatement::fetchValue<int>(int column) const
{
return fetchIntValue(column);
}
long Statement::fetchLongValue(int column) const
long BaseStatement::fetchLongValue(int column) const
{
return long(fetchValue<long long>(column));
}
template<>
long Statement::fetchValue<long>(int column) const
long BaseStatement::fetchValue<long>(int column) const
{
return fetchLongValue(column);
}
long long Statement::fetchLongLongValue(int column) const
long long BaseStatement::fetchLongLongValue(int column) const
{
checkIfIsReadyToFetchValues();
checkColumnIsValid(column);
@@ -477,12 +458,12 @@ long long Statement::fetchLongLongValue(int column) const
}
template<>
long long Statement::fetchValue<long long>(int column) const
long long BaseStatement::fetchValue<long long>(int column) const
{
return fetchLongLongValue(column);
}
double Statement::fetchDoubleValue(int column) const
double BaseStatement::fetchDoubleValue(int column) const
{
checkIfIsReadyToFetchValues();
checkColumnIsValid(column);
@@ -490,62 +471,30 @@ double Statement::fetchDoubleValue(int column) const
}
template<>
double Statement::fetchValue<double>(int column) const
double BaseStatement::fetchValue<double>(int column) const
{
return fetchDoubleValue(column);
}
template<typename StringType>
StringType Statement::fetchValue(int column) const
StringType BaseStatement::fetchValue(int column) const
{
checkIfIsReadyToFetchValues();
checkColumnIsValid(column);
return convertToTextForColumn<StringType>(m_compiledStatement.get(), column);
}
Utils::SmallString Statement::fetchSmallStringValue(int column) const
Utils::SmallString BaseStatement::fetchSmallStringValue(int column) const
{
return fetchValue<Utils::SmallString>(column);
}
Utils::PathString Statement::fetchPathStringValue(int column) const
Utils::PathString BaseStatement::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 fetchValue<Utils::SmallString>(column);
}
template <typename ContainerType>
ContainerType Statement::columnValues(const std::vector<int> &columnIndices) const
{
using ElementType = typename ContainerType::value_type;
ContainerType valueContainer;
valueContainer.reserve(columnIndices.size());
for (int columnIndex : columnIndices)
valueContainer.push_back(fetchValue<ElementType>(columnIndex));
return valueContainer;
}
template <typename Type>
Type Statement::toValue(Utils::SmallStringView sqlStatement, Database &database)
{
Statement statement(sqlStatement, database);
statement.next();
return statement.fetchValue<Type>(0);
}
template SQLITE_EXPORT int Statement::toValue<int>(Utils::SmallStringView sqlStatement, Database &database);
template SQLITE_EXPORT long long Statement::toValue<long long>(Utils::SmallStringView sqlStatement, Database &database);
template SQLITE_EXPORT double Statement::toValue<double>(Utils::SmallStringView sqlStatement, Database &database);
template SQLITE_EXPORT Utils::SmallString Statement::toValue<Utils::SmallString>(Utils::SmallStringView sqlStatement, Database &database);
template SQLITE_EXPORT Utils::SmallString BaseStatement::fetchValue<Utils::SmallString>(int column) const;
template SQLITE_EXPORT Utils::PathString BaseStatement::fetchValue<Utils::PathString>(int column) const;
} // namespace Sqlite

View File

@@ -48,10 +48,10 @@ namespace Sqlite {
class Database;
class DatabaseBackend;
class SQLITE_EXPORT Statement
class SQLITE_EXPORT BaseStatement
{
protected:
explicit Statement(Utils::SmallStringView sqlStatement, Database &database);
public:
explicit BaseStatement(Utils::SmallStringView sqlStatement, Database &database);
static void deleteCompiledStatement(sqlite3_stmt *m_compiledStatement);
@@ -68,7 +68,6 @@ protected:
Utils::PathString fetchPathStringValue(int column) const;
template<typename Type>
Type fetchValue(int column) const;
Utils::SmallString text(int column) const;
int columnCount() const;
Utils::SmallStringVector columnNames() const;
@@ -87,140 +86,11 @@ protected:
bind(index, static_cast<long long>(value));
}
void bindValues()
{
}
template<typename... ValueType>
void bindValues(const ValueType&... values)
{
bindValuesByIndex(1, values...);
}
template<typename... ValueType>
void write(const ValueType&... values)
{
bindValuesByIndex(1, values...);
execute();
}
template<typename... ValueType>
void bindNameValues(const ValueType&... values)
{
bindValuesByName(values...);
}
template<typename... ValueType>
void writeNamed(const ValueType&... values)
{
bindValuesByName(values...);
execute();
}
template <typename Type>
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 ResultType,
int ResultTypeCount = 1>
std::vector<ResultType> values(std::size_t reserveSize)
{
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
while (next())
emplaceBackValues<ResultTypeCount>(resultValues);
reset();
return resultValues;
}
template <typename ResultType,
int ResultTypeCount = 1,
typename... QueryTypes>
std::vector<ResultType> values(std::size_t reserveSize, const QueryTypes&... queryValues)
{
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
bindValues(queryValues...);
while (next())
emplaceBackValues<ResultTypeCount>(resultValues);
reset();
return resultValues;
}
template <typename ResultType,
int ResultTypeCount = 1,
typename QueryElementType>
std::vector<ResultType> values(std::size_t reserveSize,
const std::vector<QueryElementType> &queryValues)
{
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
for (const QueryElementType &queryValue : queryValues) {
bindValues(queryValue);
while (next())
emplaceBackValues<ResultTypeCount>(resultValues);
reset();
}
return resultValues;
}
template <typename ResultType,
int ResultTypeCount = 1,
typename... QueryElementTypes>
std::vector<ResultType> values(std::size_t reserveSize,
const std::vector<std::tuple<QueryElementTypes...>> &queryTuples)
{
using Container = std::vector<ResultType>;
Container resultValues;
resultValues.reserve(reserveSize);
for (const auto &queryTuple : queryTuples) {
bindTupleValues(queryTuple);
while (next())
emplaceBackValues<ResultTypeCount>(resultValues);
reset();
}
return resultValues;
}
template <typename ResultType,
int ResultTypeCount = 1,
typename... QueryTypes>
Utils::optional<ResultType> value( const QueryTypes&... queryValues)
{
Utils::optional<ResultType> resultValue;
bindValues(queryValues...);
if (next())
resultValue = assignValue<Utils::optional<ResultType>, ResultTypeCount>();
reset();
return resultValue;
}
template <typename Type>
static Type toValue(Utils::SmallStringView sqlStatement, Database &database);
void prepare(Utils::SmallStringView sqlStatement);
void waitForUnlockNotify() const;
@@ -236,7 +106,6 @@ protected:
void checkColumnIsValid(int column) const;
void checkBindingName(int index) const;
void setBindingParameterCount();
void setBindingColumnNamesFromStatement();
void setColumnCount();
bool isReadOnlyStatement() const;
[[noreturn]] void throwStatementIsBusy(const char *whatHasHappened) const;
@@ -250,22 +119,185 @@ protected:
[[noreturn]] void throwUnknowError(const char *whatHasHappened) const;
[[noreturn]] void throwBingingTooBig(const char *whatHasHappened) const;
template <typename ContainerType>
ContainerType columnValues(const std::vector<int> &columnIndices) const;
QString columnName(int column) const;
Database &database() const;
protected:
explicit Statement(Utils::SmallStringView sqlStatement,
DatabaseBackend &databaseBackend);
private:
std::unique_ptr<sqlite3_stmt, void (*)(sqlite3_stmt*)> m_compiledStatement;
Database &m_database;
int m_bindingParameterCount;
int m_columnCount;
mutable bool m_isReadyToFetchValues;
};
extern template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, int value);
extern template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, long value);
extern template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, long long value);
extern template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, double value);
extern template SQLITE_EXPORT void BaseStatement::bind(Utils::SmallStringView name, Utils::SmallStringView text);
template <> SQLITE_EXPORT int BaseStatement::fetchValue<int>(int column) const;
template <> SQLITE_EXPORT long BaseStatement::fetchValue<long>(int column) const;
template <> SQLITE_EXPORT long long BaseStatement::fetchValue<long long>(int column) const;
template <> SQLITE_EXPORT double BaseStatement::fetchValue<double>(int column) const;
extern template SQLITE_EXPORT Utils::SmallString BaseStatement::fetchValue<Utils::SmallString>(int column) const;
extern template SQLITE_EXPORT Utils::PathString BaseStatement::fetchValue<Utils::PathString>(int column) const;
template <typename BaseStatement>
class SQLITE_EXPORT StatementImplementation : public BaseStatement
{
public:
using BaseStatement::BaseStatement;
void bindValues()
{
}
template<typename... ValueType>
void bindValues(const ValueType&... values)
{
bindValuesByIndex(1, values...);
}
template<typename... ValueType>
void write(const ValueType&... values)
{
bindValuesByIndex(1, values...);
BaseStatement::execute();
}
template<typename... ValueType>
void bindNameValues(const ValueType&... values)
{
bindValuesByName(values...);
}
template<typename... ValueType>
void writeNamed(const ValueType&... values)
{
bindValuesByName(values...);
BaseStatement::execute();
}
template <typename ResultType,
int ResultTypeCount = 1>
std::vector<ResultType> values(std::size_t reserveSize)
{
Resetter resetter{*this};
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
while (BaseStatement::next())
emplaceBackValues<ResultTypeCount>(resultValues);
return resultValues;
}
template <typename ResultType,
int ResultTypeCount = 1,
typename... QueryTypes>
std::vector<ResultType> values(std::size_t reserveSize, const QueryTypes&... queryValues)
{
Resetter resetter{*this};
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
bindValues(queryValues...);
while (BaseStatement::next())
emplaceBackValues<ResultTypeCount>(resultValues);
return resultValues;
}
template <typename ResultType,
int ResultTypeCount = 1,
typename QueryElementType>
std::vector<ResultType> values(std::size_t reserveSize,
const std::vector<QueryElementType> &queryValues)
{
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
for (const QueryElementType &queryValue : queryValues) {
Resetter resetter{*this};
bindValues(queryValue);
while (BaseStatement::next())
emplaceBackValues<ResultTypeCount>(resultValues);
}
return resultValues;
}
template <typename ResultType,
int ResultTypeCount = 1,
typename... QueryElementTypes>
std::vector<ResultType> values(std::size_t reserveSize,
const std::vector<std::tuple<QueryElementTypes...>> &queryTuples)
{
using Container = std::vector<ResultType>;
Container resultValues;
resultValues.reserve(reserveSize);
for (const auto &queryTuple : queryTuples) {
Resetter resetter{*this};
bindTupleValues(queryTuple);
while (BaseStatement::next())
emplaceBackValues<ResultTypeCount>(resultValues);
}
return resultValues;
}
template <typename ResultType,
int ResultTypeCount = 1,
typename... QueryTypes>
Utils::optional<ResultType> value(const QueryTypes&... queryValues)
{
Resetter resetter{*this};
Utils::optional<ResultType> resultValue;
bindValues(queryValues...);
if (BaseStatement::next())
resultValue = assignValue<Utils::optional<ResultType>, ResultTypeCount>();
return resultValue;
}
template <typename Type>
static Type toValue(Utils::SmallStringView sqlStatement, Database &database)
{
StatementImplementation statement(sqlStatement, database);
statement.next();
return statement.template fetchValue<Type>(0);
}
private:
class ValueGetter
struct Resetter
{
public:
ValueGetter(Statement &statement, int column)
Resetter(StatementImplementation &statement)
: statement(statement)
{}
~Resetter()
{
statement.reset();
}
StatementImplementation &statement;
};
struct ValueGetter
{
ValueGetter(StatementImplementation &statement, int column)
: statement(statement),
column(column)
{}
@@ -300,7 +332,7 @@ private:
return statement.fetchPathStringValue(column);
}
Statement &statement;
StatementImplementation &statement;
int column;
};
@@ -335,26 +367,26 @@ private:
template<typename ValueType>
void bindValuesByIndex(int index, const ValueType &value)
{
bind(index, value);
BaseStatement::bind(index, value);
}
template<typename ValueType, typename... ValueTypes>
void bindValuesByIndex(int index, const ValueType &value, const ValueTypes&... values)
{
bind(index, value);
BaseStatement::bind(index, value);
bindValuesByIndex(index + 1, values...);
}
template<typename ValueType>
void bindValuesByName(Utils::SmallStringView name, const ValueType &value)
{
bind(bindingIndexForName(name), value);
BaseStatement::bind(BaseStatement::bindingIndexForName(name), value);
}
template<typename ValueType, typename... ValueTypes>
void bindValuesByName(Utils::SmallStringView name, const ValueType &value, const ValueTypes&... values)
{
bind(bindingIndexForName(name), value);
BaseStatement::bind(BaseStatement::bindingIndexForName(name), value);
bindValuesByName(values...);
}
@@ -371,30 +403,6 @@ private:
bindTupleValuesElement(element, ColumnIndices());
}
private:
std::unique_ptr<sqlite3_stmt, void (*)(sqlite3_stmt*)> m_compiledStatement;
Utils::SmallStringVector m_bindingColumnNames;
Database &m_database;
int m_bindingParameterCount;
int m_columnCount;
mutable bool m_isReadyToFetchValues;
};
extern template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, int value);
extern template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, long value);
extern template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, long long value);
extern template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, double value);
extern template SQLITE_EXPORT void Statement::bind(Utils::SmallStringView name, Utils::SmallStringView text);
extern template SQLITE_EXPORT int Statement::toValue<int>(Utils::SmallStringView sqlStatement, Database &database);
extern template SQLITE_EXPORT long long Statement::toValue<long long>(Utils::SmallStringView sqlStatement, Database &database);
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::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

@@ -28,7 +28,7 @@
#include "sqliteexception.h"
#include "sqlitereadstatement.h"
#include "sqlitereadwritestatement.h"
#include "sqlitestatement.h"
#include "sqlitebasestatement.h"
#include "sqlitewritestatement.h"
#include <QFileInfo>

View File

@@ -125,10 +125,10 @@ public:
}
};
class WrongBingingName : public Exception
class WrongBindingName : public Exception
{
public:
WrongBingingName(const char *whatErrorHasHappen)
WrongBindingName(const char *whatErrorHasHappen)
: Exception(whatErrorHasHappen)
{
}

View File

@@ -31,7 +31,7 @@ namespace Sqlite {
ReadStatement::ReadStatement(Utils::SmallStringView sqlStatement,
Database &database)
: Statement(sqlStatement, database)
: StatementImplementation(sqlStatement, database)
{
checkIsReadOnlyStatement();
}

View File

@@ -25,19 +25,18 @@
#pragma once
#include "sqlitestatement.h"
#include "sqlitebasestatement.h"
namespace Sqlite {
class SQLITE_EXPORT ReadStatement final : private Statement
class SQLITE_EXPORT ReadStatement final : protected StatementImplementation<BaseStatement>
{
public:
explicit ReadStatement(Utils::SmallStringView sqlStatement, Database &database);
using Statement::value;
using Statement::values;
using Statement::toValue;
using Statement::database;
using StatementImplementation::value;
using StatementImplementation::values;
using StatementImplementation::toValue;
protected:
void checkIsReadOnlyStatement();

View File

@@ -29,7 +29,7 @@ namespace Sqlite {
ReadWriteStatement::ReadWriteStatement(Utils::SmallStringView sqlStatement,
Database &database)
: Statement(sqlStatement, database)
: StatementImplementation(sqlStatement, database)
{
}

View File

@@ -25,24 +25,23 @@
#pragma once
#include "sqlitestatement.h"
#include "sqlitebasestatement.h"
namespace Sqlite {
class SQLITE_EXPORT ReadWriteStatement final : private Statement
class SQLITE_EXPORT ReadWriteStatement final : protected StatementImplementation<BaseStatement>
{
friend class DatabaseBackend;
public:
ReadWriteStatement(Utils::SmallStringView sqlStatement, Database &database);
using Statement::execute;
using Statement::value;
using Statement::values;
using Statement::toValue;
using Statement::database;
using Statement::write;
using Statement::writeNamed;
using StatementImplementation::execute;
using StatementImplementation::value;
using StatementImplementation::values;
using StatementImplementation::toValue;
using StatementImplementation::write;
using StatementImplementation::writeNamed;
};
} // namespace Sqlite

View File

@@ -29,7 +29,7 @@ namespace Sqlite {
WriteStatement::WriteStatement(Utils::SmallStringView sqlStatement,
Database &database)
: Statement(sqlStatement, database)
: StatementImplementation(sqlStatement, database)
{
checkIsWritableStatement();
}

View File

@@ -25,19 +25,19 @@
#pragma once
#include "sqlitestatement.h"
#include "sqlitebasestatement.h"
namespace Sqlite {
class SQLITE_EXPORT WriteStatement : private Statement
class SQLITE_EXPORT WriteStatement : protected StatementImplementation<BaseStatement>
{
public:
explicit WriteStatement(Utils::SmallStringView sqlStatement, Database &database);
using Statement::execute;
using Statement::database;
using Statement::write;
using Statement::writeNamed;
using StatementImplementation::execute;
using StatementImplementation::database;
using StatementImplementation::write;
using StatementImplementation::writeNamed;
protected:
void checkIsWritableStatement();