forked from qt-creator/qt-creator
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:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "sqliteexception.h"
|
||||
#include "sqlitereadstatement.h"
|
||||
#include "sqlitereadwritestatement.h"
|
||||
#include "sqlitestatement.h"
|
||||
#include "sqlitebasestatement.h"
|
||||
#include "sqlitewritestatement.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
@@ -125,10 +125,10 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class WrongBingingName : public Exception
|
||||
class WrongBindingName : public Exception
|
||||
{
|
||||
public:
|
||||
WrongBingingName(const char *whatErrorHasHappen)
|
||||
WrongBindingName(const char *whatErrorHasHappen)
|
||||
: Exception(whatErrorHasHappen)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Sqlite {
|
||||
|
||||
ReadStatement::ReadStatement(Utils::SmallStringView sqlStatement,
|
||||
Database &database)
|
||||
: Statement(sqlStatement, database)
|
||||
: StatementImplementation(sqlStatement, database)
|
||||
{
|
||||
checkIsReadOnlyStatement();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Sqlite {
|
||||
|
||||
ReadWriteStatement::ReadWriteStatement(Utils::SmallStringView sqlStatement,
|
||||
Database &database)
|
||||
: Statement(sqlStatement, database)
|
||||
: StatementImplementation(sqlStatement, database)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Sqlite {
|
||||
|
||||
WriteStatement::WriteStatement(Utils::SmallStringView sqlStatement,
|
||||
Database &database)
|
||||
: Statement(sqlStatement, database)
|
||||
: StatementImplementation(sqlStatement, database)
|
||||
{
|
||||
checkIsWritableStatement();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user