diff --git a/src/libs/sqlite/sqlitebasestatement.h b/src/libs/sqlite/sqlitebasestatement.h index c96fb3faded..8baf1a3b230 100644 --- a/src/libs/sqlite/sqlitebasestatement.h +++ b/src/libs/sqlite/sqlitebasestatement.h @@ -29,6 +29,7 @@ #include "sqliteblob.h" #include "sqliteexception.h" +#include "sqlitetransaction.h" #include "sqlitevalue.h" #include @@ -37,6 +38,7 @@ #include #include +#include #include #include #include @@ -91,6 +93,7 @@ public: void bind(int index, Utils::span values); void bind(int index, Utils::SmallStringView value); void bind(int index, const Value &value); + void bind(int index, ValueView value); void bind(int index, BlobView blobView); void bind(int index, uint value) { bind(index, static_cast(value)); } @@ -162,13 +165,14 @@ extern template SQLITE_EXPORT Utils::PathString BaseStatement::fetchValue class StatementImplementation : public BaseStatement { + struct Resetter; public: using BaseStatement::BaseStatement; void execute() { - Resetter resetter{*this}; + Resetter resetter{this}; BaseStatement::next(); resetter.reset(); } @@ -185,7 +189,7 @@ public: template void write(const ValueType&... values) { - Resetter resetter{*this}; + Resetter resetter{this}; bindValues(values...); BaseStatement::next(); resetter.reset(); @@ -194,7 +198,7 @@ public: template std::vector values(std::size_t reserveSize) { - Resetter resetter{*this}; + Resetter resetter{this}; std::vector resultValues; resultValues.reserve(std::max(reserveSize, m_maximumResultCount)); @@ -211,7 +215,7 @@ public: template auto values(std::size_t reserveSize, const QueryTypes &...queryValues) { - Resetter resetter{*this}; + Resetter resetter{this}; std::vector resultValues; resultValues.reserve(std::max(reserveSize, m_maximumResultCount)); @@ -230,13 +234,13 @@ public: template auto value(const QueryTypes &...queryValues) { - Resetter resetter{*this}; + Resetter resetter{this}; Utils::optional resultValue; bindValues(queryValues...); if (BaseStatement::next()) - resultValue = assignValue>(); + resultValue = createOptionalValue>(); resetter.reset(); @@ -258,7 +262,7 @@ public: template void readCallback(Callable &&callable, const QueryTypes &...queryValues) { - Resetter resetter{*this}; + Resetter resetter{this}; bindValues(queryValues...); @@ -272,10 +276,10 @@ public: resetter.reset(); } - template + template void readTo(Container &container, const QueryTypes &...queryValues) { - Resetter resetter{*this}; + Resetter resetter{this}; bindValues(queryValues...); @@ -285,39 +289,187 @@ public: resetter.reset(); } + template + auto range(const QueryTypes &...queryValues) + { + return SqliteResultRange{*this, queryValues...}; + } + + template + auto rangeWithTransaction(const QueryTypes &...queryValues) + { + return SqliteResultRangeWithTransaction{*this, queryValues...}; + } + + template + class BaseSqliteResultRange + { + public: + class SqliteResultIteratator + { + public: + using iterator_category = std::input_iterator_tag; + using difference_type = int; + using value_type = ResultType; + using pointer = ResultType *; + using reference = ResultType &; + + SqliteResultIteratator(StatementImplementation &statement) + : m_statement{statement} + , m_hasNext{m_statement.next()} + {} + + SqliteResultIteratator(StatementImplementation &statement, bool hasNext) + : m_statement{statement} + , m_hasNext{hasNext} + {} + + SqliteResultIteratator &operator++() + { + m_hasNext = m_statement.next(); + return *this; + } + + void operator++(int) { m_hasNext = m_statement.next(); } + + friend bool operator==(const SqliteResultIteratator &first, + const SqliteResultIteratator &second) + { + return first.m_hasNext == second.m_hasNext; + } + + friend bool operator!=(const SqliteResultIteratator &first, + const SqliteResultIteratator &second) + { + return !(first == second); + } + + value_type operator*() const { return m_statement.createValue(); } + + private: + StatementImplementation &m_statement; + bool m_hasNext = false; + }; + + using value_type = ResultType; + using iterator = SqliteResultIteratator; + using const_iterator = iterator; + + template + BaseSqliteResultRange(StatementImplementation &statement, const QueryTypes &...queryValues) + : m_statement{statement} + { + statement.bindValues(queryValues...); + } + + BaseSqliteResultRange(BaseSqliteResultRange &) = delete; + BaseSqliteResultRange &operator=(BaseSqliteResultRange &) = delete; + + BaseSqliteResultRange(BaseSqliteResultRange &&other) + : m_statement{std::move(other.resetter)} + {} + BaseSqliteResultRange &operator=(BaseSqliteResultRange &&) = delete; + + iterator begin() & { return iterator{m_statement}; } + iterator end() & { return iterator{m_statement, false}; } + + const_iterator begin() const & { return iterator{m_statement}; } + const_iterator end() const & { return iterator{m_statement, false}; } + + private: + StatementImplementation &m_statement; + }; + + template + class SqliteResultRange : public BaseSqliteResultRange + { + public: + template + SqliteResultRange(StatementImplementation &statement, const QueryTypes &...queryValues) + : BaseSqliteResultRange{statement} + , resetter{&statement} + + { + statement.bindValues(queryValues...); + } + + ~SqliteResultRange() + { + if (!std::uncaught_exceptions()) + resetter.reset(); + } + + private: + Resetter resetter; + }; + + template + class SqliteResultRangeWithTransaction : public BaseSqliteResultRange + { + public: + template + SqliteResultRangeWithTransaction(StatementImplementation &statement, + const QueryTypes &...queryValues) + : BaseSqliteResultRange{statement} + , m_transaction{statement.database()} + , resetter{&statement} + { + statement.bindValues(queryValues...); + } + + ~SqliteResultRangeWithTransaction() + { + if (!std::uncaught_exceptions()) { + resetter.reset(); + m_transaction.commit(); + } + } + + private: + DeferredTransaction m_transaction; + Resetter resetter; + }; + protected: ~StatementImplementation() = default; private: struct Resetter { - Resetter(StatementImplementation &statement) + Resetter(StatementImplementation *statement) : statement(statement) {} + Resetter(Resetter &) = delete; + Resetter &operator=(Resetter &) = delete; + + Resetter(Resetter &&other) + : statement{std::exchange(other.statement, nullptr)} + {} + void reset() { try { - statement.reset(); + if (statement) + statement->reset(); } catch (...) { - shouldReset = false; + statement = nullptr; throw; } - shouldReset = false; + statement = nullptr; } ~Resetter() noexcept { try { - if (shouldReset) - statement.reset(); + if (statement) + statement->reset(); } catch (...) { } } - StatementImplementation &statement; - bool shouldReset = true; + StatementImplementation *statement; }; struct ValueGetter @@ -351,17 +503,28 @@ private: emplaceBackValues(container, std::make_integer_sequence{}); } - template - ResultOptionalType assignValue(std::integer_sequence) + template + ResultOptionalType createOptionalValue(std::integer_sequence) { return ResultOptionalType(Utils::in_place, ValueGetter(*this, ColumnIndices)...); } template - ResultOptionalType assignValue() + ResultOptionalType createOptionalValue() { - return assignValue(std::make_integer_sequence{}); + return createOptionalValue(std::make_integer_sequence{}); + } + + template + ResultType createValue(std::integer_sequence) + { + return ResultType{ValueGetter(*this, ColumnIndices)...}; + } + + template + ResultType createValue() + { + return createValue(std::make_integer_sequence{}); } template diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp index 489d7951c13..c35539942b5 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.cpp +++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp @@ -213,8 +213,7 @@ QmlDesignerPlugin::~QmlDesignerPlugin() bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString *errorMessage/* = 0*/) { Sqlite::LibraryInitializer::initialize(); - - QDir{}.mkpath(Core::ICore::cacheResourcePath()); + QDir{}.mkpath(Core::ICore::cacheResourcePath().toString()); if (!Utils::HostOsInfo::canCreateOpenGLContext(errorMessage)) return false; @@ -222,8 +221,10 @@ bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString *e if (DesignerSettings::getValue(DesignerSettingsKey::STANDALONE_MODE).toBool()) GenerateResource::generateMenuEntry(); - QString fontPath = Core::ICore::resourcePath() + - QStringLiteral("/qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf"); + const QString fontPath + = Core::ICore::resourcePath( + "qmldesigner/propertyEditorQmlSources/imports/StudioTheme/icons.ttf") + .toString(); if (QFontDatabase::addApplicationFont(fontPath) < 0) qCWarning(qmldesignerLog) << "Could not add font " << fontPath << "to font database";