From d4c6f06a63ad38043158f8a399cbc8974437c5f8 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Tue, 7 Dec 2021 17:28:38 +0100 Subject: [PATCH] Sqlite: Introduce BindParameterCount template parameter The BindParameterCount is checked at compile time and then again for the construction of the statement. So we provide an early error instead of an some error later or even stranger behavior. Change-Id: I860ca1f78645c222ae1accf5c7a469c77befc3bd Reviewed-by: Qt CI Bot Reviewed-by: Reviewed-by: Tim Jenssen --- src/libs/sqlite/sqlitebasestatement.cpp | 48 +--- src/libs/sqlite/sqlitebasestatement.h | 20 +- src/libs/sqlite/sqlitedatabase.h | 16 +- src/libs/sqlite/sqliteexception.h | 12 +- src/libs/sqlite/sqlitereadstatement.h | 8 +- src/libs/sqlite/sqlitereadwritestatement.h | 8 +- src/libs/sqlite/sqlitesessions.h | 2 +- src/libs/sqlite/sqlitewritestatement.h | 16 +- .../imagecache/imagecachestorage.h | 17 +- .../projectstorage/projectstorage.h | 237 ++++++++-------- .../unit/unittest/imagecachestorage-test.cpp | 18 +- tests/unit/unittest/mocksqlitestatement.h | 7 +- tests/unit/unittest/sqlitealgorithms-test.cpp | 7 +- tests/unit/unittest/sqlitedatabase-test.cpp | 38 +-- tests/unit/unittest/sqlitedatabasemock.h | 11 +- tests/unit/unittest/sqlitereadstatementmock.h | 2 +- .../unittest/sqlitereadwritestatementmock.h | 2 +- tests/unit/unittest/sqlitesessions-test.cpp | 27 +- tests/unit/unittest/sqlitestatement-test.cpp | 256 +++++++++--------- tests/unit/unittest/sqliteteststatement.h | 7 +- .../unittest/sqlitewritestatementmock.cpp | 4 +- .../unit/unittest/sqlitewritestatementmock.h | 13 +- 22 files changed, 389 insertions(+), 387 deletions(-) diff --git a/src/libs/sqlite/sqlitebasestatement.cpp b/src/libs/sqlite/sqlitebasestatement.cpp index 459913060f4..932828a625f 100644 --- a/src/libs/sqlite/sqlitebasestatement.cpp +++ b/src/libs/sqlite/sqlitebasestatement.cpp @@ -51,12 +51,8 @@ namespace Sqlite { BaseStatement::BaseStatement(Utils::SmallStringView sqlStatement, Database &database) : m_compiledStatement(nullptr, deleteCompiledStatement) , m_database(database) - , m_bindingParameterCount(0) - , m_columnCount(0) { prepare(sqlStatement); - setBindingParameterCount(); - setColumnCount(); } void BaseStatement::deleteCompiledStatement(sqlite3_stmt *compiledStatement) @@ -141,11 +137,6 @@ void BaseStatement::step() const next(); } -int BaseStatement::columnCount() const -{ - return m_columnCount; -} - void BaseStatement::bind(int index, NullValue) { int resultCode = sqlite3_bind_null(m_compiledStatement.get(), index); @@ -512,34 +503,16 @@ void BaseStatement::checkForBindingError(int resultCode) const throwUnknowError("SqliteStatement::bind: unknown error has happened"); } +void BaseStatement::checkBindingParameterCount(int bindingParameterCount) const +{ + if (bindingParameterCount != sqlite3_bind_parameter_count(m_compiledStatement.get())) + throw WrongBindingParameterCount{"Sqlite: wrong binding parameter count!"}; +} + void BaseStatement::checkColumnCount(int columnCount) const { - if (columnCount != m_columnCount) - throw ColumnCountDoesNotMatch("SqliteStatement::values: column count does not match!"); -} - -void BaseStatement::checkBindingName(int index) const -{ - if (index <= 0 || index > m_bindingParameterCount) - throwWrongBingingName("SqliteStatement::bind: binding name are not exists in this statement!"); -} - -void BaseStatement::setBindingParameterCount() -{ - m_bindingParameterCount = sqlite3_bind_parameter_count(m_compiledStatement.get()); -} - -Utils::SmallStringView chopFirstLetter(const char *rawBindingName) -{ - if (rawBindingName != nullptr) - return Utils::SmallStringView(++rawBindingName); - - return Utils::SmallStringView(""); -} - -void BaseStatement::setColumnCount() -{ - m_columnCount = sqlite3_column_count(m_compiledStatement.get()); + if (columnCount != sqlite3_column_count(m_compiledStatement.get())) + throw WrongColumnCount{"Sqlite: wrong column count!"}; } bool BaseStatement::isReadOnlyStatement() const @@ -582,11 +555,6 @@ void BaseStatement::throwBindingIndexIsOutOfRange(const char *whatHasHappened) c throw BindingIndexIsOutOfRange(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); } -void BaseStatement::throwWrongBingingName(const char *whatHasHappened) const -{ - throw WrongBindingName(whatHasHappened); -} - void BaseStatement::throwUnknowError(const char *whatHasHappened) const { if (sqliteDatabaseHandle()) diff --git a/src/libs/sqlite/sqlitebasestatement.h b/src/libs/sqlite/sqlitebasestatement.h index 8ba9de09e89..aa7fb11c7eb 100644 --- a/src/libs/sqlite/sqlitebasestatement.h +++ b/src/libs/sqlite/sqlitebasestatement.h @@ -80,7 +80,6 @@ public: BlobView fetchBlobValue(int column) const; template Type fetchValue(int column) const; - int columnCount() const; void bind(int index, NullValue); void bind(int index, int value); @@ -112,10 +111,9 @@ public: [[noreturn]] void checkForPrepareError(int resultCode) const; [[noreturn]] void checkForBindingError(int resultCode) const; void setIfIsReadyToFetchValues(int resultCode) const; - void checkColumnCount(int columnCount) const; void checkBindingName(int index) const; - void setBindingParameterCount(); - void setColumnCount(); + void checkBindingParameterCount(int bindingParameterCount) const; + void checkColumnCount(int columnCount) const; bool isReadOnlyStatement() const; [[noreturn]] void throwStatementIsBusy(const char *whatHasHappened) const; [[noreturn]] void throwStatementHasError(const char *whatHasHappened) const; @@ -149,8 +147,6 @@ protected: private: std::unique_ptr m_compiledStatement; Database &m_database; - int m_bindingParameterCount; - int m_columnCount; }; template <> SQLITE_EXPORT int BaseStatement::fetchValue(int column) const; @@ -161,7 +157,7 @@ extern template SQLITE_EXPORT Utils::SmallStringView BaseStatement::fetchValue(int column) const; extern template SQLITE_EXPORT Utils::PathString BaseStatement::fetchValue(int column) const; -template +template class StatementImplementation : public BaseStatement { struct Resetter; @@ -175,11 +171,11 @@ public: BaseStatement::next(); } - void bindValues() {} - template - void bindValues(const ValueType&... values) + void bindValues(const ValueType &...values) { + static_assert(BindParameterCount == sizeof...(values), "Wrong binding parameter count!"); + int index = 0; (BaseStatement::bind(++index, values), ...); } @@ -344,10 +340,9 @@ public: using const_iterator = iterator; template - BaseSqliteResultRange(StatementImplementation &statement, const QueryTypes &...queryValues) + BaseSqliteResultRange(StatementImplementation &statement) : m_statement{statement} { - statement.bindValues(queryValues...); } BaseSqliteResultRange(BaseSqliteResultRange &) = delete; @@ -376,7 +371,6 @@ public: SqliteResultRange(StatementImplementation &statement, const QueryTypes &...queryValues) : BaseSqliteResultRange{statement} , resetter{&statement} - { statement.bindValues(queryValues...); } diff --git a/src/libs/sqlite/sqlitedatabase.h b/src/libs/sqlite/sqlitedatabase.h index 588cabf3749..b379e2f80f1 100644 --- a/src/libs/sqlite/sqlitedatabase.h +++ b/src/libs/sqlite/sqlitedatabase.h @@ -45,10 +45,11 @@ namespace Sqlite { using namespace std::chrono_literals; -template +template class ReadStatement; +template class WriteStatement; -template +template class ReadWriteStatement; class SQLITE_EXPORT Database final : public TransactionInterface, public DatabaseInterface @@ -59,11 +60,12 @@ class SQLITE_EXPORT Database final : public TransactionInterface, public Databas public: using MutexType = std::mutex; - template - using ReadStatement = Sqlite::ReadStatement; - using WriteStatement = Sqlite::WriteStatement; - template - using ReadWriteStatement = Sqlite::ReadWriteStatement; + template + using ReadStatement = Sqlite::ReadStatement; + template + using WriteStatement = Sqlite::WriteStatement; + template + using ReadWriteStatement = Sqlite::ReadWriteStatement; using BusyHandler = DatabaseBackend::BusyHandler; Database(); diff --git a/src/libs/sqlite/sqliteexception.h b/src/libs/sqlite/sqliteexception.h index 6dbf92951ae..44f7806662f 100644 --- a/src/libs/sqlite/sqliteexception.h +++ b/src/libs/sqlite/sqliteexception.h @@ -104,12 +104,6 @@ public: using Exception::Exception; }; -class ColumnCountDoesNotMatch : public Exception -{ -public: - using Exception::Exception; -}; - class BindingIndexIsOutOfRange : public ExceptionWithMessage { public: @@ -326,4 +320,10 @@ public: using Exception::Exception; }; +class WrongColumnCount : public Exception +{ +public: + using Exception::Exception; +}; + } // namespace Sqlite diff --git a/src/libs/sqlite/sqlitereadstatement.h b/src/libs/sqlite/sqlitereadstatement.h index 09906a3d902..58eafc3e424 100644 --- a/src/libs/sqlite/sqlitereadstatement.h +++ b/src/libs/sqlite/sqlitereadstatement.h @@ -29,16 +29,18 @@ namespace Sqlite { -template -class ReadStatement final : protected StatementImplementation +template +class ReadStatement final + : protected StatementImplementation { - using Base = StatementImplementation; + using Base = StatementImplementation; public: ReadStatement(Utils::SmallStringView sqlStatement, Database &database) : Base{sqlStatement, database} { checkIsReadOnlyStatement(); + Base::checkBindingParameterCount(BindParameterCount); Base::checkColumnCount(ResultCount); } diff --git a/src/libs/sqlite/sqlitereadwritestatement.h b/src/libs/sqlite/sqlitereadwritestatement.h index e33b247f077..4ac9617996b 100644 --- a/src/libs/sqlite/sqlitereadwritestatement.h +++ b/src/libs/sqlite/sqlitereadwritestatement.h @@ -29,16 +29,18 @@ namespace Sqlite { -template -class ReadWriteStatement final : protected StatementImplementation +template +class ReadWriteStatement final + : protected StatementImplementation { friend class DatabaseBackend; - using Base = StatementImplementation; + using Base = StatementImplementation; public: ReadWriteStatement(Utils::SmallStringView sqlStatement, Database &database) : Base{sqlStatement, database} { + Base::checkBindingParameterCount(BindParameterCount); Base::checkColumnCount(ResultCount); } diff --git a/src/libs/sqlite/sqlitesessions.h b/src/libs/sqlite/sqlitesessions.h index da5fe336df6..0d1baeec477 100644 --- a/src/libs/sqlite/sqlitesessions.h +++ b/src/libs/sqlite/sqlitesessions.h @@ -88,7 +88,7 @@ private: public: Database &database; - WriteStatement insertSession; + WriteStatement<1> insertSession; Utils::SmallString databaseName; Utils::SmallStringVector tableNames; std::unique_ptr session; diff --git a/src/libs/sqlite/sqlitewritestatement.h b/src/libs/sqlite/sqlitewritestatement.h index 1a0bb5832ca..cbea0d5b3fd 100644 --- a/src/libs/sqlite/sqlitewritestatement.h +++ b/src/libs/sqlite/sqlitewritestatement.h @@ -28,21 +28,23 @@ #include "sqlitebasestatement.h" namespace Sqlite { - -class WriteStatement : protected StatementImplementation +template +class WriteStatement : protected StatementImplementation { - using Base = StatementImplementation; + using Base = StatementImplementation; public: WriteStatement(Utils::SmallStringView sqlStatement, Database &database) - : StatementImplementation(sqlStatement, database) + : Base(sqlStatement, database) { checkIsWritableStatement(); + Base::checkBindingParameterCount(BindParameterCount); + Base::checkColumnCount(0); } - using StatementImplementation::database; - using StatementImplementation::execute; - using StatementImplementation::write; + using Base::database; + using Base::execute; + using Base::write; protected: void checkIsWritableStatement() diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecachestorage.h b/src/plugins/qmldesigner/designercore/imagecache/imagecachestorage.h index 3b320634da0..2f7e2eb93e6 100644 --- a/src/plugins/qmldesigner/designercore/imagecache/imagecachestorage.h +++ b/src/plugins/qmldesigner/designercore/imagecache/imagecachestorage.h @@ -43,9 +43,10 @@ template class ImageCacheStorage : public ImageCacheStorageInterface { public: - template - using ReadStatement = typename DatabaseType::template ReadStatement; - using WriteStatement = typename DatabaseType::WriteStatement; + template + using ReadStatement = typename DatabaseType::template ReadStatement; + template + using WriteStatement = typename DatabaseType::template WriteStatement; ImageCacheStorage(DatabaseType &database) : database(database) @@ -273,18 +274,18 @@ public: DatabaseType &database; Initializer initializer{database}; Sqlite::ImmediateNonThrowingDestructorTransaction transaction{database}; - mutable ReadStatement<1> selectImageStatement{ + mutable ReadStatement<1, 2> selectImageStatement{ "SELECT image FROM images WHERE name=?1 AND mtime >= ?2", database}; - mutable ReadStatement<1> selectSmallImageStatement{ + mutable ReadStatement<1, 2> selectSmallImageStatement{ "SELECT smallImage FROM images WHERE name=?1 AND mtime >= ?2", database}; - mutable ReadStatement<1> selectIconStatement{ + mutable ReadStatement<1, 2> selectIconStatement{ "SELECT icon FROM icons WHERE name=?1 AND mtime >= ?2", database}; - WriteStatement upsertImageStatement{ + WriteStatement<4> upsertImageStatement{ "INSERT INTO images(name, mtime, image, smallImage) VALUES (?1, ?2, ?3, ?4) ON " "CONFLICT(name) DO UPDATE SET mtime=excluded.mtime, image=excluded.image, " "smallImage=excluded.smallImage", database}; - WriteStatement upsertIconStatement{ + WriteStatement<3> upsertIconStatement{ "INSERT INTO icons(name, mtime, icon) VALUES (?1, ?2, ?3) ON " "CONFLICT(name) DO UPDATE SET mtime=excluded.mtime, icon=excluded.icon", database}; diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h index 3f10cbe8175..92b189e8629 100644 --- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h +++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.h @@ -47,11 +47,12 @@ template class ProjectStorage final : public ProjectStorageInterface { public: - template - using ReadStatement = typename Database::template ReadStatement; - template - using ReadWriteStatement = typename Database::template ReadWriteStatement; - using WriteStatement = typename Database::WriteStatement; + template + using ReadStatement = typename Database::template ReadStatement; + template + using ReadWriteStatement = typename Database::template ReadWriteStatement; + template + using WriteStatement = typename Database::template WriteStatement; ProjectStorage(Database &database, bool isInitialized) : database{database} @@ -2137,18 +2138,18 @@ public: Database &database; Initializer initializer; ModuleCache moduleCache{ModuleStorageAdapter{*this}}; - ReadWriteStatement<1> upsertTypeStatement{ + ReadWriteStatement<1, 3> upsertTypeStatement{ "INSERT INTO types(sourceId, name, accessSemantics) VALUES(?1, ?2, ?3) ON CONFLICT DO " "UPDATE SET accessSemantics=excluded.accessSemantics WHERE accessSemantics IS NOT " "excluded.accessSemantics RETURNING typeId", database}; - WriteStatement updatePrototypeStatement{ + WriteStatement<3> updatePrototypeStatement{ "UPDATE types SET prototypeId=?2, prototypeNameId=?3 WHERE typeId=?1 AND (prototypeId IS " "NOT ?2 OR prototypeNameId IS NOT ?3)", database}; - mutable ReadStatement<1> selectTypeIdByExportedNameStatement{ + mutable ReadStatement<1, 1> selectTypeIdByExportedNameStatement{ "SELECT typeId FROM exportedTypeNames WHERE name=?1", database}; - mutable ReadStatement<1> selectPrototypeIdStatement{ + mutable ReadStatement<1, 2> selectPrototypeIdStatement{ "WITH RECURSIVE " " typeSelection(typeId) AS (" " VALUES(?1) " @@ -2157,7 +2158,7 @@ public: " IS NOT NULL)" "SELECT typeId FROM typeSelection WHERE typeId=?2 LIMIT 1", database}; - mutable ReadStatement<1> selectPropertyDeclarationIdByTypeIdAndNameStatement{ + mutable ReadStatement<1, 2> selectPropertyDeclarationIdByTypeIdAndNameStatement{ "WITH RECURSIVE " " typeSelection(typeId, level) AS (" " VALUES(?1, 0) " @@ -2167,7 +2168,7 @@ public: "SELECT propertyDeclarationId FROM propertyDeclarations JOIN typeSelection USING(typeId) " " WHERE name=?2 ORDER BY level LIMIT 1", database}; - mutable ReadStatement<3> selectPropertyDeclarationByTypeIdAndNameStatement{ + mutable ReadStatement<3, 2> selectPropertyDeclarationByTypeIdAndNameStatement{ "WITH RECURSIVE " " typeSelection(typeId, level) AS (" " VALUES(?1, 0) " @@ -2178,7 +2179,7 @@ public: " FROM propertyDeclarations JOIN typeSelection USING(typeId) " " WHERE name=?2 ORDER BY level LIMIT 1", database}; - mutable ReadStatement<1> selectPrototypeIdsStatement{ + mutable ReadStatement<1, 1> selectPrototypeIdsStatement{ "WITH RECURSIVE " " typeSelection(typeId, level) AS (" " VALUES(?1, 0) " @@ -2187,69 +2188,69 @@ public: " USING(typeId) WHERE prototypeId IS NOT NULL) " "SELECT typeId FROM typeSelection ORDER BY level DESC", database}; - mutable ReadStatement<1> selectSourceContextIdFromSourceContextsBySourceContextPathStatement{ + mutable ReadStatement<1, 1> selectSourceContextIdFromSourceContextsBySourceContextPathStatement{ "SELECT sourceContextId FROM sourceContexts WHERE sourceContextPath = ?", database}; - mutable ReadStatement<1> selectSourceContextPathFromSourceContextsBySourceContextIdStatement{ + mutable ReadStatement<1, 1> selectSourceContextPathFromSourceContextsBySourceContextIdStatement{ "SELECT sourceContextPath FROM sourceContexts WHERE sourceContextId = ?", database}; mutable ReadStatement<2> selectAllSourceContextsStatement{ "SELECT sourceContextPath, sourceContextId FROM sourceContexts", database}; - WriteStatement insertIntoSourceContextsStatement{ + WriteStatement<1> insertIntoSourceContextsStatement{ "INSERT INTO sourceContexts(sourceContextPath) VALUES (?)", database}; - mutable ReadStatement<1> selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatement{ + mutable ReadStatement<1, 2> selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatement{ "SELECT sourceId FROM sources WHERE sourceContextId = ? AND sourceName = ?", database}; - mutable ReadStatement<2> selectSourceNameAndSourceContextIdFromSourcesBySourceIdStatement{ + mutable ReadStatement<2, 1> selectSourceNameAndSourceContextIdFromSourcesBySourceIdStatement{ "SELECT sourceName, sourceContextId FROM sources WHERE sourceId = ?", database}; - mutable ReadStatement<1> selectSourceContextIdFromSourcesBySourceIdStatement{ + mutable ReadStatement<1, 1> selectSourceContextIdFromSourcesBySourceIdStatement{ "SELECT sourceContextId FROM sources WHERE sourceId = ?", database}; - WriteStatement insertIntoSourcesStatement{ + WriteStatement<2> insertIntoSourcesStatement{ "INSERT INTO sources(sourceContextId, sourceName) VALUES (?,?)", database}; mutable ReadStatement<3> selectAllSourcesStatement{ "SELECT sourceName, sourceContextId, sourceId FROM sources", database}; - mutable ReadStatement<4> selectTypeByTypeIdStatement{ + mutable ReadStatement<4, 1> selectTypeByTypeIdStatement{ "SELECT sourceId, name, prototypeId, accessSemantics FROM types WHERE typeId=?", database}; - mutable ReadStatement<4> selectExportedTypesByTypeIdStatement{ + mutable ReadStatement<4, 1> selectExportedTypesByTypeIdStatement{ "SELECT moduleId, name, ifnull(majorVersion, -1), ifnull(minorVersion, -1) FROM " "exportedTypeNames WHERE typeId=?", database}; mutable ReadStatement<5> selectTypesStatement{ "SELECT sourceId, name, typeId, ifnull(prototypeId, -1), accessSemantics FROM types", database}; - ReadStatement<1> selectNotUpdatedTypesInSourcesStatement{ + ReadStatement<1, 2> selectNotUpdatedTypesInSourcesStatement{ "SELECT DISTINCT typeId FROM types WHERE (sourceId IN carray(?1) AND typeId NOT IN " "carray(?2))", database}; - WriteStatement deleteTypeNamesByTypeIdStatement{"DELETE FROM exportedTypeNames WHERE typeId=?", - database}; - WriteStatement deleteEnumerationDeclarationByTypeIdStatement{ + WriteStatement<1> deleteTypeNamesByTypeIdStatement{ + "DELETE FROM exportedTypeNames WHERE typeId=?", database}; + WriteStatement<1> deleteEnumerationDeclarationByTypeIdStatement{ "DELETE FROM enumerationDeclarations WHERE typeId=?", database}; - WriteStatement deletePropertyDeclarationByTypeIdStatement{ + WriteStatement<1> deletePropertyDeclarationByTypeIdStatement{ "DELETE FROM propertyDeclarations WHERE typeId=?", database}; - WriteStatement deleteFunctionDeclarationByTypeIdStatement{ + WriteStatement<1> deleteFunctionDeclarationByTypeIdStatement{ "DELETE FROM functionDeclarations WHERE typeId=?", database}; - WriteStatement deleteSignalDeclarationByTypeIdStatement{ + WriteStatement<1> deleteSignalDeclarationByTypeIdStatement{ "DELETE FROM signalDeclarations WHERE typeId=?", database}; - WriteStatement deleteTypeStatement{"DELETE FROM types WHERE typeId=?", database}; - mutable ReadStatement<4> selectPropertyDeclarationsByTypeIdStatement{ + WriteStatement<1> deleteTypeStatement{"DELETE FROM types WHERE typeId=?", database}; + mutable ReadStatement<4, 1> selectPropertyDeclarationsByTypeIdStatement{ "SELECT name, nullif(propertyTypeId, -1), propertyTraits, (SELECT name FROM " "propertyDeclarations WHERE propertyDeclarationId=pd.aliasPropertyDeclarationId) FROM " "propertyDeclarations AS pd WHERE typeId=?", database}; - ReadStatement<6> selectPropertyDeclarationsForTypeIdStatement{ + ReadStatement<6, 1> selectPropertyDeclarationsForTypeIdStatement{ "SELECT name, propertyTraits, propertyTypeId, propertyImportedTypeNameId, " "propertyDeclarationId, ifnull(aliasPropertyDeclarationId, -1) FROM propertyDeclarations " "WHERE typeId=? ORDER BY name", database}; - ReadWriteStatement<1> insertPropertyDeclarationStatement{ + ReadWriteStatement<1, 5> insertPropertyDeclarationStatement{ "INSERT INTO propertyDeclarations(typeId, name, propertyTypeId, propertyTraits, " "propertyImportedTypeNameId, aliasPropertyDeclarationId) VALUES(?1, ?2, ?3, ?4, ?5, NULL) " "RETURNING propertyDeclarationId", database}; - WriteStatement updatePropertyDeclarationStatement{ + WriteStatement<4> updatePropertyDeclarationStatement{ "UPDATE propertyDeclarations SET propertyTypeId=?2, propertyTraits=?3, " "propertyImportedTypeNameId=?4, aliasPropertyDeclarationId=NULL WHERE " "propertyDeclarationId=?1", database}; - WriteStatement updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement{ + WriteStatement<3> updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement{ "WITH RECURSIVE " " properties(aliasPropertyDeclarationId) AS ( " " SELECT propertyDeclarationId FROM propertyDeclarations WHERE " @@ -2262,7 +2263,7 @@ public: "FROM properties AS p " "WHERE pd.propertyDeclarationId=p.aliasPropertyDeclarationId", database}; - WriteStatement updatePropertyAliasDeclarationRecursivelyStatement{ + WriteStatement<1> updatePropertyAliasDeclarationRecursivelyStatement{ "WITH RECURSIVE " " propertyValues(propertyTypeId, propertyTraits) AS (" " SELECT propertyTypeId, propertyTraits FROM propertyDeclarations " @@ -2278,120 +2279,120 @@ public: "FROM properties AS p, propertyValues AS pv " "WHERE pd.propertyDeclarationId=p.aliasPropertyDeclarationId", database}; - WriteStatement deletePropertyDeclarationStatement{ + WriteStatement<1> deletePropertyDeclarationStatement{ "DELETE FROM propertyDeclarations WHERE propertyDeclarationId=?", database}; - ReadStatement<3> selectPropertyDeclarationsWithAliasForTypeIdStatement{ + ReadStatement<3, 1> selectPropertyDeclarationsWithAliasForTypeIdStatement{ "SELECT name, propertyDeclarationId, aliasPropertyDeclarationId FROM propertyDeclarations " "WHERE typeId=? AND aliasPropertyDeclarationId IS NOT NULL ORDER BY name", database}; - WriteStatement updatePropertyDeclarationWithAliasAndTypeStatement{ + WriteStatement<5> updatePropertyDeclarationWithAliasAndTypeStatement{ "UPDATE propertyDeclarations SET propertyTypeId=?2, propertyTraits=?3, " "propertyImportedTypeNameId=?4, aliasPropertyDeclarationId=?5 WHERE " "propertyDeclarationId=?1", database}; - ReadWriteStatement<1> insertAliasPropertyDeclarationStatement{ + ReadWriteStatement<1, 2> insertAliasPropertyDeclarationStatement{ "INSERT INTO propertyDeclarations(typeId, name) VALUES(?1, ?2) RETURNING " "propertyDeclarationId", database}; - mutable ReadStatement<4> selectFunctionDeclarationsForTypeIdStatement{ + mutable ReadStatement<4, 1> selectFunctionDeclarationsForTypeIdStatement{ "SELECT name, returnTypeName, signature, functionDeclarationId FROM " "functionDeclarations WHERE typeId=? ORDER BY name", database}; - mutable ReadStatement<3> selectFunctionDeclarationsForTypeIdWithoutSignatureStatement{ + mutable ReadStatement<3, 1> selectFunctionDeclarationsForTypeIdWithoutSignatureStatement{ "SELECT name, returnTypeName, functionDeclarationId FROM " "functionDeclarations WHERE typeId=? ORDER BY name", database}; - mutable ReadStatement<3> selectFunctionParameterDeclarationsStatement{ + mutable ReadStatement<3, 1> selectFunctionParameterDeclarationsStatement{ "SELECT json_extract(json_each.value, '$.n'), json_extract(json_each.value, '$.tn'), " "json_extract(json_each.value, '$.tr') FROM functionDeclarations, " "json_each(functionDeclarations.signature) WHERE functionDeclarationId=?", database}; - WriteStatement insertFunctionDeclarationStatement{ + WriteStatement<4> insertFunctionDeclarationStatement{ "INSERT INTO functionDeclarations(typeId, name, returnTypeName, signature) VALUES(?1, ?2, " "?3, ?4)", database}; - WriteStatement updateFunctionDeclarationStatement{ + WriteStatement<3> updateFunctionDeclarationStatement{ "UPDATE functionDeclarations SET returnTypeName=?2, signature=?3 WHERE " "functionDeclarationId=?1", database}; - WriteStatement deleteFunctionDeclarationStatement{ + WriteStatement<1> deleteFunctionDeclarationStatement{ "DELETE FROM functionDeclarations WHERE functionDeclarationId=?", database}; - mutable ReadStatement<3> selectSignalDeclarationsForTypeIdStatement{ + mutable ReadStatement<3, 1> selectSignalDeclarationsForTypeIdStatement{ "SELECT name, signature, signalDeclarationId FROM signalDeclarations WHERE typeId=? ORDER " "BY name", database}; - mutable ReadStatement<2> selectSignalDeclarationsForTypeIdWithoutSignatureStatement{ + mutable ReadStatement<2, 1> selectSignalDeclarationsForTypeIdWithoutSignatureStatement{ "SELECT name, signalDeclarationId FROM signalDeclarations WHERE typeId=? ORDER BY name", database}; - mutable ReadStatement<3> selectSignalParameterDeclarationsStatement{ + mutable ReadStatement<3, 1> selectSignalParameterDeclarationsStatement{ "SELECT json_extract(json_each.value, '$.n'), json_extract(json_each.value, '$.tn'), " "json_extract(json_each.value, '$.tr') FROM signalDeclarations, " "json_each(signalDeclarations.signature) WHERE signalDeclarationId=?", database}; - WriteStatement insertSignalDeclarationStatement{ + WriteStatement<3> insertSignalDeclarationStatement{ "INSERT INTO signalDeclarations(typeId, name, signature) VALUES(?1, ?2, ?3)", database}; - WriteStatement updateSignalDeclarationStatement{ + WriteStatement<2> updateSignalDeclarationStatement{ "UPDATE signalDeclarations SET signature=?2 WHERE signalDeclarationId=?1", database}; - WriteStatement deleteSignalDeclarationStatement{ + WriteStatement<1> deleteSignalDeclarationStatement{ "DELETE FROM signalDeclarations WHERE signalDeclarationId=?", database}; - mutable ReadStatement<3> selectEnumerationDeclarationsForTypeIdStatement{ + mutable ReadStatement<3, 1> selectEnumerationDeclarationsForTypeIdStatement{ "SELECT name, enumeratorDeclarations, enumerationDeclarationId FROM " "enumerationDeclarations WHERE typeId=? ORDER BY name", database}; - mutable ReadStatement<2> selectEnumerationDeclarationsForTypeIdWithoutEnumeratorDeclarationsStatement{ + mutable ReadStatement<2, 1> selectEnumerationDeclarationsForTypeIdWithoutEnumeratorDeclarationsStatement{ "SELECT name, enumerationDeclarationId FROM enumerationDeclarations WHERE typeId=? ORDER " "BY name", database}; - mutable ReadStatement<3> selectEnumeratorDeclarationStatement{ + mutable ReadStatement<3, 1> selectEnumeratorDeclarationStatement{ "SELECT json_each.key, json_each.value, json_each.type!='null' FROM " "enumerationDeclarations, json_each(enumerationDeclarations.enumeratorDeclarations) WHERE " "enumerationDeclarationId=?", database}; - WriteStatement insertEnumerationDeclarationStatement{ + WriteStatement<3> insertEnumerationDeclarationStatement{ "INSERT INTO enumerationDeclarations(typeId, name, enumeratorDeclarations) VALUES(?1, ?2, " "?3)", database}; - WriteStatement updateEnumerationDeclarationStatement{ + WriteStatement<2> updateEnumerationDeclarationStatement{ "UPDATE enumerationDeclarations SET enumeratorDeclarations=?2 WHERE " "enumerationDeclarationId=?1", database}; - WriteStatement deleteEnumerationDeclarationStatement{ + WriteStatement<1> deleteEnumerationDeclarationStatement{ "DELETE FROM enumerationDeclarations WHERE enumerationDeclarationId=?", database}; - mutable ReadStatement<1> selectModuleIdByNameStatement{ + mutable ReadStatement<1, 1> selectModuleIdByNameStatement{ "SELECT moduleId FROM modules WHERE name=? LIMIT 1", database}; - mutable ReadWriteStatement<1> insertModuleNameStatement{ + mutable ReadWriteStatement<1, 1> insertModuleNameStatement{ "INSERT INTO modules(name) VALUES(?1) RETURNING moduleId", database}; - mutable ReadStatement<1> selectModuleNameStatement{ + mutable ReadStatement<1, 1> selectModuleNameStatement{ "SELECT name FROM modules WHERE moduleId =?1", database}; mutable ReadStatement<2> selectAllModulesStatement{"SELECT name, moduleId FROM modules", database}; - mutable ReadStatement<1> selectTypeIdBySourceIdAndNameStatement{ + mutable ReadStatement<1, 2> selectTypeIdBySourceIdAndNameStatement{ "SELECT typeId FROM types WHERE sourceId=?1 and name=?2", database}; - mutable ReadStatement<1> selectTypeIdByModuleIdsAndExportedNameStatement{ + mutable ReadStatement<1, 3> selectTypeIdByModuleIdsAndExportedNameStatement{ "SELECT typeId FROM exportedTypeNames WHERE moduleId IN carray(?1, ?2, 'int32') AND " "name=?3", database}; - mutable ReadStatement<5> selectDocumentImportForSourceIdStatement{ + mutable ReadStatement<5, 1> selectDocumentImportForSourceIdStatement{ "SELECT importId, sourceId, moduleId, ifnull(majorVersion, -1), ifnull(minorVersion, -1) " "FROM documentImports WHERE sourceId IN carray(?1) ORDER BY sourceId, moduleId, " "majorVersion, minorVersion", database}; - WriteStatement insertDocumentImportWithoutVersionStatement{ + WriteStatement<2> insertDocumentImportWithoutVersionStatement{ "INSERT INTO documentImports(sourceId, moduleId) " "VALUES (?1, ?2)", database}; - WriteStatement insertDocumentImportWithMajorVersionStatement{ + WriteStatement<3> insertDocumentImportWithMajorVersionStatement{ "INSERT INTO documentImports(sourceId, moduleId, majorVersion) " "VALUES (?1, ?2, ?3)", database}; - WriteStatement insertDocumentImportWithVersionStatement{ + WriteStatement<4> insertDocumentImportWithVersionStatement{ "INSERT INTO documentImports(sourceId, moduleId, majorVersion, minorVersion) " "VALUES (?1, ?2, ?3, ?4)", database}; - WriteStatement deleteDocumentImportStatement{"DELETE FROM documentImports WHERE importId=?1", - database}; - WriteStatement deleteDocumentImportsWithSourceIdsStatement{ + WriteStatement<1> deleteDocumentImportStatement{"DELETE FROM documentImports WHERE importId=?1", + database}; + WriteStatement<1> deleteDocumentImportsWithSourceIdsStatement{ "DELETE FROM documentImports WHERE sourceId IN carray(?1)", database}; - ReadStatement<1> selectPropertyDeclarationIdPrototypeChainDownStatement{ + ReadStatement<1, 2> selectPropertyDeclarationIdPrototypeChainDownStatement{ "WITH RECURSIVE " " typeSelection(typeId, level) AS (" " SELECT prototypeId, 0 FROM types WHERE typeId=?1 AND prototypeId IS NOT NULL" @@ -2401,22 +2402,22 @@ public: "SELECT propertyDeclarationId FROM typeSelection JOIN propertyDeclarations " " USING(typeId) WHERE name=?2 ORDER BY level LIMIT 1", database}; - WriteStatement updateAliasIdPropertyDeclarationStatement{ + WriteStatement<2> updateAliasIdPropertyDeclarationStatement{ "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=?2 WHERE " "aliasPropertyDeclarationId=?1", database}; - WriteStatement updateAliasPropertyDeclarationByAliasPropertyDeclarationIdStatement{ + WriteStatement<2> updateAliasPropertyDeclarationByAliasPropertyDeclarationIdStatement{ "UPDATE propertyDeclarations SET propertyTypeId=new.propertyTypeId, " "propertyTraits=new.propertyTraits, aliasPropertyDeclarationId=?1 FROM (SELECT " "propertyTypeId, propertyTraits FROM propertyDeclarations WHERE propertyDeclarationId=?1) " "AS new WHERE aliasPropertyDeclarationId=?2", database}; - WriteStatement updateAliasPropertyDeclarationToNullStatement{ + WriteStatement<1> updateAliasPropertyDeclarationToNullStatement{ "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=NULL, propertyTypeId=NULL, " "propertyTraits=NULL WHERE propertyDeclarationId=? AND (aliasPropertyDeclarationId IS NOT " "NULL OR propertyTypeId IS NOT NULL OR propertyTraits IS NOT NULL)", database}; - ReadStatement<4> selectAliasPropertiesDeclarationForPropertiesWithTypeIdStatement{ + ReadStatement<4, 1> selectAliasPropertiesDeclarationForPropertiesWithTypeIdStatement{ "SELECT alias.typeId, alias.propertyDeclarationId, alias.propertyImportedTypeNameId, " "target.propertyDeclarationId FROM propertyDeclarations AS alias JOIN propertyDeclarations " "AS target ON alias.aliasPropertyDeclarationId=target.propertyDeclarationId WHERE " @@ -2424,7 +2425,7 @@ public: "(SELECT importedTypeNameId FROM exportedTypeNames JOIN importedTypeNames USING(name) " "WHERE typeId=?1)", database}; - ReadStatement<3> selectAliasPropertiesDeclarationForPropertiesWithAliasIdStatement{ + ReadStatement<3, 1> selectAliasPropertiesDeclarationForPropertiesWithAliasIdStatement{ "WITH RECURSIVE " " properties(propertyDeclarationId, propertyImportedTypeNameId, typeId, " " aliasPropertyDeclarationId) AS (" @@ -2438,22 +2439,22 @@ public: "SELECT propertyDeclarationId, propertyImportedTypeNameId, aliasPropertyDeclarationId " " FROM properties", database}; - ReadWriteStatement<3> updatesPropertyDeclarationPropertyTypeToNullStatement{ + ReadWriteStatement<3, 1> updatesPropertyDeclarationPropertyTypeToNullStatement{ "UPDATE propertyDeclarations SET propertyTypeId=NULL WHERE propertyTypeId=?1 AND " "aliasPropertyDeclarationId IS NULL RETURNING typeId, propertyDeclarationId, " "propertyImportedTypeNameId", database}; - ReadStatement<1> selectPropertyNameStatement{ + ReadStatement<1, 1> selectPropertyNameStatement{ "SELECT name FROM propertyDeclarations WHERE propertyDeclarationId=?", database}; - WriteStatement updatePropertyDeclarationTypeStatement{ + WriteStatement<2> updatePropertyDeclarationTypeStatement{ "UPDATE propertyDeclarations SET propertyTypeId=?2 WHERE propertyDeclarationId=?1", database}; - ReadWriteStatement<2> updatePrototypeIdToNullStatement{ + ReadWriteStatement<2, 1> updatePrototypeIdToNullStatement{ "UPDATE types SET prototypeId=NULL WHERE prototypeId=?1 RETURNING " "typeId, prototypeNameId", database}; - WriteStatement updateTypePrototypeStatement{"UPDATE types SET prototypeId=?2 WHERE typeId=?1", - database}; - mutable ReadStatement<1> selectTypeIdsForPrototypeChainIdStatement{ + WriteStatement<2> updateTypePrototypeStatement{ + "UPDATE types SET prototypeId=?2 WHERE typeId=?1", database}; + mutable ReadStatement<1, 1> selectTypeIdsForPrototypeChainIdStatement{ "WITH RECURSIVE " " prototypes(typeId) AS (" " SELECT prototypeId FROM types WHERE typeId=? AND prototypeId IS NOT NULL" @@ -2462,12 +2463,12 @@ public: " IS NOT NULL)" "SELECT typeId FROM prototypes", database}; - WriteStatement updatePropertyDeclarationAliasIdAndTypeNameIdStatement{ + WriteStatement<3> updatePropertyDeclarationAliasIdAndTypeNameIdStatement{ "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=?2, " "propertyImportedTypeNameId=?3 WHERE propertyDeclarationId=?1 AND " "(aliasPropertyDeclarationId IS NOT ?2 OR propertyImportedTypeNameId IS NOT ?3)", database}; - WriteStatement updatetPropertiesDeclarationValuesOfAliasStatement{ + WriteStatement<1> updatetPropertiesDeclarationValuesOfAliasStatement{ "WITH RECURSIVE " " properties(propertyDeclarationId, propertyTypeId, propertyTraits) AS ( " " SELECT aliasPropertyDeclarationId, propertyTypeId, propertyTraits FROM " @@ -2482,11 +2483,11 @@ public: " (pd.propertyTypeId IS NOT p.propertyTypeId OR pd.propertyTraits IS NOT " " p.propertyTraits)", database}; - WriteStatement updatePropertyDeclarationAliasIdToNullStatement{ + WriteStatement<1> updatePropertyDeclarationAliasIdToNullStatement{ "UPDATE propertyDeclarations SET aliasPropertyDeclarationId=NULL WHERE " "propertyDeclarationId=?1", database}; - mutable ReadStatement<1> selectPropertyDeclarationIdsForAliasChainStatement{ + mutable ReadStatement<1, 1> selectPropertyDeclarationIdsForAliasChainStatement{ "WITH RECURSIVE " " properties(propertyDeclarationId) AS ( " " SELECT aliasPropertyDeclarationId FROM propertyDeclarations WHERE " @@ -2498,43 +2499,44 @@ public: database}; mutable ReadStatement<3> selectAllFileStatusesStatement{ "SELECT sourceId, size, lastModified FROM fileStatuses ORDER BY sourceId", database}; - mutable ReadStatement<3> selectFileStatusesForSourceIdsStatement{ + mutable ReadStatement<3, 1> selectFileStatusesForSourceIdsStatement{ "SELECT sourceId, size, lastModified FROM fileStatuses WHERE sourceId IN carray(?1) ORDER " "BY sourceId", database}; - mutable ReadStatement<3> selectFileStatusesForSourceIdStatement{ + mutable ReadStatement<3, 1> selectFileStatusesForSourceIdStatement{ "SELECT sourceId, size, lastModified FROM fileStatuses WHERE sourceId=?1 ORDER BY sourceId", database}; - WriteStatement insertFileStatusStatement{ + WriteStatement<3> insertFileStatusStatement{ "INSERT INTO fileStatuses(sourceId, size, lastModified) VALUES(?1, ?2, ?3)", database}; - WriteStatement deleteFileStatusStatement{"DELETE FROM fileStatuses WHERE sourceId=?1", database}; - WriteStatement updateFileStatusStatement{ + WriteStatement<1> deleteFileStatusStatement{"DELETE FROM fileStatuses WHERE sourceId=?1", + database}; + WriteStatement<3> updateFileStatusStatement{ "UPDATE fileStatuses SET size=?2, lastModified=?3 WHERE sourceId=?1", database}; - ReadStatement<1> selectTypeIdBySourceIdStatement{"SELECT typeId FROM types WHERE sourceId=?", - database}; - mutable ReadStatement<1> selectImportedTypeNameIdStatement{ + ReadStatement<1, 1> selectTypeIdBySourceIdStatement{"SELECT typeId FROM types WHERE sourceId=?", + database}; + mutable ReadStatement<1, 3> selectImportedTypeNameIdStatement{ "SELECT importedTypeNameId FROM importedTypeNames WHERE kind=?1 AND importOrSourceId=?2 " "AND name=?3 LIMIT 1", database}; - mutable ReadWriteStatement<1> insertImportedTypeNameIdStatement{ + mutable ReadWriteStatement<1, 3> insertImportedTypeNameIdStatement{ "INSERT INTO importedTypeNames(kind, importOrSourceId, name) VALUES (?1, ?2, ?3) " "RETURNING importedTypeNameId", database}; - mutable ReadStatement<1> selectImportIdBySourceIdAndModuleIdStatement{ + mutable ReadStatement<1, 2> selectImportIdBySourceIdAndModuleIdStatement{ "SELECT importId FROM documentImports WHERE sourceId=?1 AND moduleId=?2 AND majorVersion " "IS NULL AND minorVersion IS NULL LIMIT 1", database}; - mutable ReadStatement<1> selectImportIdBySourceIdAndModuleIdAndMajorVersionStatement{ + mutable ReadStatement<1, 3> selectImportIdBySourceIdAndModuleIdAndMajorVersionStatement{ "SELECT importId FROM documentImports WHERE sourceId=?1 AND moduleId=?2 AND " "majorVersion=?3 AND minorVersion IS NULL LIMIT 1", database}; - mutable ReadStatement<1> selectImportIdBySourceIdAndModuleIdAndVersionStatement{ + mutable ReadStatement<1, 4> selectImportIdBySourceIdAndModuleIdAndVersionStatement{ "SELECT importId FROM documentImports WHERE sourceId=?1 AND moduleId=?2 AND " "majorVersion=?3 AND minorVersion=?4 LIMIT 1", database}; - mutable ReadStatement<1> selectKindFromImportedTypeNamesStatement{ + mutable ReadStatement<1, 1> selectKindFromImportedTypeNamesStatement{ "SELECT kind FROM importedTypeNames WHERE importedTypeNameId=?1", database}; - mutable ReadStatement<1> selectTypeIdForQualifiedImportedTypeNameNamesStatement{ + mutable ReadStatement<1, 1> selectTypeIdForQualifiedImportedTypeNameNamesStatement{ "SELECT typeId FROM importedTypeNames AS itn JOIN documentImports AS di ON " "importOrSourceId=importId JOIN exportedTypeNames AS etn USING(moduleId) WHERE " "itn.kind=2 AND importedTypeNameId=?1 AND itn.name=etn.name AND " @@ -2542,7 +2544,7 @@ public: "NULL OR di.minorVersion>=etn.minorVersion))) ORDER BY etn.majorVersion DESC NULLS FIRST, " "etn.minorVersion DESC NULLS FIRST LIMIT 1", database}; - mutable ReadStatement<1> selectTypeIdForImportedTypeNameNamesStatement{ + mutable ReadStatement<1, 1> selectTypeIdForImportedTypeNameNamesStatement{ "SELECT typeId FROM importedTypeNames AS itn JOIN documentImports AS di ON " "importOrSourceId=sourceId JOIN exportedTypeNames AS etn USING(moduleId) WHERE " "itn.kind=1 AND importedTypeNameId=?1 AND itn.name=etn.name AND " @@ -2550,44 +2552,45 @@ public: "NULL OR di.minorVersion>=etn.minorVersion))) ORDER BY etn.majorVersion DESC NULLS FIRST, " "etn.minorVersion DESC NULLS FIRST LIMIT 1", database}; - WriteStatement deleteAllSourcesStatement{"DELETE FROM sources", database}; - WriteStatement deleteAllSourceContextsStatement{"DELETE FROM sourceContexts", database}; - mutable ReadStatement<6> selectExportedTypesForSourceIdsStatement{ + WriteStatement<0> deleteAllSourcesStatement{"DELETE FROM sources", database}; + WriteStatement<0> deleteAllSourceContextsStatement{"DELETE FROM sourceContexts", database}; + mutable ReadStatement<6, 1> selectExportedTypesForSourceIdsStatement{ "SELECT moduleId, name, ifnull(majorVersion, -1), ifnull(minorVersion, -1), typeId, " "exportedTypeNameId FROM exportedTypeNames WHERE typeId in carray(?1) ORDER BY moduleId, " "name, majorVersion, minorVersion", database}; - WriteStatement insertExportedTypeNamesWithVersionStatement{ + WriteStatement<5> insertExportedTypeNamesWithVersionStatement{ "INSERT INTO exportedTypeNames(moduleId, name, majorVersion, minorVersion, typeId) " "VALUES(?1, ?2, ?3, ?4, ?5)", database}; - WriteStatement insertExportedTypeNamesWithMajorVersionStatement{ + WriteStatement<4> insertExportedTypeNamesWithMajorVersionStatement{ "INSERT INTO exportedTypeNames(moduleId, name, majorVersion, typeId) " "VALUES(?1, ?2, ?3, ?4)", database}; - WriteStatement insertExportedTypeNamesWithoutVersionStatement{ + WriteStatement<3> insertExportedTypeNamesWithoutVersionStatement{ "INSERT INTO exportedTypeNames(moduleId, name, typeId) VALUES(?1, ?2, ?3)", database}; - WriteStatement deleteExportedTypeNameStatement{ + WriteStatement<1> deleteExportedTypeNameStatement{ "DELETE FROM exportedTypeNames WHERE exportedTypeNameId=?", database}; - WriteStatement updateExportedTypeNameTypeIdStatement{ + WriteStatement<2> updateExportedTypeNameTypeIdStatement{ "UPDATE exportedTypeNames SET typeId=?2 WHERE exportedTypeNameId=?1", database}; - mutable ReadStatement<4> selectProjectDatasForModuleIdsStatement{ + mutable ReadStatement<4, 1> selectProjectDatasForModuleIdsStatement{ "SELECT projectSourceId, sourceId, moduleId, fileType FROM projectDatas WHERE " "projectSourceId IN carray(?1) ORDER BY projectSourceId, sourceId", database}; - WriteStatement insertProjectDataStatement{"INSERT INTO projectDatas(projectSourceId, sourceId, " - "moduleId, fileType) VALUES(?1, ?2, ?3, ?4)", - database}; - WriteStatement deleteProjectDataStatement{ + WriteStatement<4> insertProjectDataStatement{ + "INSERT INTO projectDatas(projectSourceId, sourceId, " + "moduleId, fileType) VALUES(?1, ?2, ?3, ?4)", + database}; + WriteStatement<2> deleteProjectDataStatement{ "DELETE FROM projectDatas WHERE projectSourceId=?1 AND sourceId=?2", database}; - WriteStatement updateProjectDataStatement{ + WriteStatement<4> updateProjectDataStatement{ "UPDATE projectDatas SET moduleId=?3, fileType=?4 WHERE projectSourceId=?1 AND sourceId=?2", database}; - mutable ReadStatement<4> selectProjectDatasForModuleIdStatement{ + mutable ReadStatement<4, 1> selectProjectDatasForModuleIdStatement{ "SELECT projectSourceId, sourceId, moduleId, fileType FROM projectDatas WHERE " "projectSourceId=?1", database}; - ReadStatement<1> selectTypeIdsForSourceIdsStatement{ + ReadStatement<1, 1> selectTypeIdsForSourceIdsStatement{ "SELECT typeId FROM types WHERE sourceId IN carray(?1)", database}; }; diff --git a/tests/unit/unittest/imagecachestorage-test.cpp b/tests/unit/unittest/imagecachestorage-test.cpp index 50995e6c407..73098c8cd5b 100644 --- a/tests/unit/unittest/imagecachestorage-test.cpp +++ b/tests/unit/unittest/imagecachestorage-test.cpp @@ -55,17 +55,19 @@ MATCHER_P2(IsIconEntry, class ImageCacheStorageTest : public testing::Test { protected: - template - using ReadStatement = QmlDesigner::ImageCacheStorage::ReadStatement; - using WriteStatement = QmlDesigner::ImageCacheStorage::WriteStatement; + template + using ReadStatement = QmlDesigner::ImageCacheStorage< + SqliteDatabaseMock>::ReadStatement; + template + using WriteStatement = QmlDesigner::ImageCacheStorage::WriteStatement; NiceMock databaseMock; QmlDesigner::ImageCacheStorage storage{databaseMock}; - ReadStatement<1> &selectImageStatement = storage.selectImageStatement; - ReadStatement<1> &selectSmallImageStatement = storage.selectSmallImageStatement; - ReadStatement<1> &selectIconStatement = storage.selectIconStatement; - WriteStatement &upsertImageStatement = storage.upsertImageStatement; - WriteStatement &upsertIconStatement = storage.upsertIconStatement; + ReadStatement<1, 2> &selectImageStatement = storage.selectImageStatement; + ReadStatement<1, 2> &selectSmallImageStatement = storage.selectSmallImageStatement; + ReadStatement<1, 2> &selectIconStatement = storage.selectIconStatement; + WriteStatement<4> &upsertImageStatement = storage.upsertImageStatement; + WriteStatement<3> &upsertIconStatement = storage.upsertIconStatement; QImage image1{10, 10, QImage::Format_ARGB32}; QImage smallImage1{10, 10, QImage::Format_ARGB32}; QIcon icon1{QPixmap::fromImage(image1)}; diff --git a/tests/unit/unittest/mocksqlitestatement.h b/tests/unit/unittest/mocksqlitestatement.h index a05c160371f..6e10384fbcc 100644 --- a/tests/unit/unittest/mocksqlitestatement.h +++ b/tests/unit/unittest/mocksqlitestatement.h @@ -64,6 +64,7 @@ public: MOCK_METHOD1(prepare, void(Utils::SmallStringView sqlStatement)); MOCK_METHOD1(checkColumnCount, void(int)); + MOCK_METHOD1(checkBindingParameterCount, void(int)); MOCK_CONST_METHOD0(isReadOnlyStatement, bool()); @@ -109,11 +110,11 @@ Utils::PathString BaseMockSqliteStatement::fetchValue(int col return fetchPathStringValue(column); } -template +template class MockSqliteStatement - : public Sqlite::StatementImplementation, ResultCount> + : public Sqlite::StatementImplementation, ResultCount, BindParameterCount> { - using Base = Sqlite::StatementImplementation, ResultCount>; + using Base = Sqlite::StatementImplementation, ResultCount, BindParameterCount>; public: explicit MockSqliteStatement(SqliteDatabaseMock &databaseMock) diff --git a/tests/unit/unittest/sqlitealgorithms-test.cpp b/tests/unit/unittest/sqlitealgorithms-test.cpp index 462814a67df..a1647979fa8 100644 --- a/tests/unit/unittest/sqlitealgorithms-test.cpp +++ b/tests/unit/unittest/sqlitealgorithms-test.cpp @@ -121,9 +121,10 @@ protected: database}; Sqlite::ReadStatement<2> selectValuesStatement{"SELECT key, value FROM data ORDER BY key", database}; - Sqlite::WriteStatement insertStatement{"INSERT INTO data(key, value) VALUES (?1, ?2)", database}; - Sqlite::WriteStatement updateStatement{"UPDATE data SET value = ?2 WHERE key=?1", database}; - Sqlite::WriteStatement deleteStatement{"DELETE FROM data WHERE key=?", database}; + Sqlite::WriteStatement<2> insertStatement{"INSERT INTO data(key, value) VALUES (?1, ?2)", + database}; + Sqlite::WriteStatement<2> updateStatement{"UPDATE data SET value = ?2 WHERE key=?1", database}; + Sqlite::WriteStatement<1> deleteStatement{"DELETE FROM data WHERE key=?", database}; std::function insert{ [&](const KeyValue &keyValue) { insertStatement.write(keyValue.key, keyValue.value); }}; std::function update{ diff --git a/tests/unit/unittest/sqlitedatabase-test.cpp b/tests/unit/unittest/sqlitedatabase-test.cpp index 4c05fcd9b07..92cdf01961c 100644 --- a/tests/unit/unittest/sqlitedatabase-test.cpp +++ b/tests/unit/unittest/sqlitedatabase-test.cpp @@ -196,7 +196,7 @@ TEST_F(SqliteDatabase, DatabaseIsNotInitializedIfDatabasePathDoesNotExistAtOpeni TEST_F(SqliteDatabase, GetChangesCount) { - Sqlite::WriteStatement statement("INSERT INTO test(name) VALUES (?)", database); + Sqlite::WriteStatement<1> statement("INSERT INTO test(name) VALUES (?)", database); statement.write(42); ASSERT_THAT(database.changesCount(), 1); @@ -204,7 +204,7 @@ TEST_F(SqliteDatabase, GetChangesCount) TEST_F(SqliteDatabase, GetTotalChangesCount) { - Sqlite::WriteStatement statement("INSERT INTO test(name) VALUES (?)", database); + Sqlite::WriteStatement<1> statement("INSERT INTO test(name) VALUES (?)", database); statement.write(42); ASSERT_THAT(database.lastInsertedRowId(), 1); @@ -212,7 +212,7 @@ TEST_F(SqliteDatabase, GetTotalChangesCount) TEST_F(SqliteDatabase, GetLastInsertedRowId) { - Sqlite::WriteStatement statement("INSERT INTO test(name) VALUES (?)", database); + Sqlite::WriteStatement<1> statement("INSERT INTO test(name) VALUES (?)", database); statement.write(42); ASSERT_THAT(database.lastInsertedRowId(), 1); @@ -265,7 +265,7 @@ TEST_F(SqliteDatabase, SetUpdateHookSet) database.setUpdateHook(this, updateHookCallback); EXPECT_CALL(callbackMock, Call(_, _, _, _)); - Sqlite::WriteStatement("INSERT INTO test(name) VALUES (?)", database).write(42); + Sqlite::WriteStatement<1>("INSERT INTO test(name) VALUES (?)", database).write(42); } TEST_F(SqliteDatabase, SetNullUpdateHook) @@ -275,7 +275,7 @@ TEST_F(SqliteDatabase, SetNullUpdateHook) database.setUpdateHook(nullptr, nullptr); EXPECT_CALL(callbackMock, Call(_, _, _, _)).Times(0); - Sqlite::WriteStatement("INSERT INTO test(name) VALUES (?)", database).write(42); + Sqlite::WriteStatement<1>("INSERT INTO test(name) VALUES (?)", database).write(42); } TEST_F(SqliteDatabase, ResetUpdateHook) @@ -285,12 +285,12 @@ TEST_F(SqliteDatabase, ResetUpdateHook) database.resetUpdateHook(); EXPECT_CALL(callbackMock, Call(_, _, _, _)).Times(0); - Sqlite::WriteStatement("INSERT INTO test(name) VALUES (?)", database).write(42); + Sqlite::WriteStatement<1>("INSERT INTO test(name) VALUES (?)", database).write(42); } TEST_F(SqliteDatabase, DeleteUpdateHookCall) { - Sqlite::WriteStatement("INSERT INTO test(name) VALUES (?)", database).write(42); + Sqlite::WriteStatement<1>("INSERT INTO test(name) VALUES (?)", database).write(42); database.setUpdateHook(this, updateHookCallback); EXPECT_CALL(callbackMock, Call(Eq(Sqlite::ChangeType::Delete), _, _, _)); @@ -304,7 +304,7 @@ TEST_F(SqliteDatabase, InsertUpdateHookCall) EXPECT_CALL(callbackMock, Call(Eq(Sqlite::ChangeType::Insert), _, _, _)); - Sqlite::WriteStatement("INSERT INTO test(name) VALUES (?)", database).write(42); + Sqlite::WriteStatement<1>("INSERT INTO test(name) VALUES (?)", database).write(42); } TEST_F(SqliteDatabase, UpdateUpdateHookCall) @@ -313,7 +313,7 @@ TEST_F(SqliteDatabase, UpdateUpdateHookCall) EXPECT_CALL(callbackMock, Call(Eq(Sqlite::ChangeType::Insert), _, _, _)); - Sqlite::WriteStatement("INSERT INTO test(name) VALUES (?)", database).write(42); + Sqlite::WriteStatement<1>("INSERT INTO test(name) VALUES (?)", database).write(42); } TEST_F(SqliteDatabase, RowIdUpdateHookCall) @@ -322,7 +322,7 @@ TEST_F(SqliteDatabase, RowIdUpdateHookCall) EXPECT_CALL(callbackMock, Call(_, _, _, Eq(42))); - Sqlite::WriteStatement("INSERT INTO test(rowid, name) VALUES (?,?)", database).write(42, "foo"); + Sqlite::WriteStatement<2>("INSERT INTO test(rowid, name) VALUES (?,?)", database).write(42, "foo"); } TEST_F(SqliteDatabase, DatabaseUpdateHookCall) @@ -331,7 +331,7 @@ TEST_F(SqliteDatabase, DatabaseUpdateHookCall) EXPECT_CALL(callbackMock, Call(_, StrEq("main"), _, _)); - Sqlite::WriteStatement("INSERT INTO test(name) VALUES (?)", database).write(42); + Sqlite::WriteStatement<1>("INSERT INTO test(name) VALUES (?)", database).write(42); } TEST_F(SqliteDatabase, TableUpdateHookCall) @@ -340,20 +340,21 @@ TEST_F(SqliteDatabase, TableUpdateHookCall) EXPECT_CALL(callbackMock, Call(_, _, StrEq("test"), _)); - Sqlite::WriteStatement("INSERT INTO test(name) VALUES (?)", database).write(42); + Sqlite::WriteStatement<1>("INSERT INTO test(name) VALUES (?)", database).write(42); } TEST_F(SqliteDatabase, SessionsCommit) { database.setAttachedTables({"test"}); - Sqlite::WriteStatement("INSERT INTO test(id, name) VALUES (?,?)", database).write(1, "foo"); + Sqlite::WriteStatement<2>("INSERT INTO test(id, name) VALUES (?,?)", database).write(1, "foo"); database.unlock(); Sqlite::ImmediateSessionTransaction transaction{database}; - Sqlite::WriteStatement("INSERT INTO test(id, name) VALUES (?,?)", database).write(2, "bar"); + Sqlite::WriteStatement<2>("INSERT INTO test(id, name) VALUES (?,?)", database).write(2, "bar"); transaction.commit(); database.lock(); - Sqlite::WriteStatement("INSERT OR REPLACE INTO test(id, name) VALUES (?,?)", database).write(2, "hoo"); + Sqlite::WriteStatement<2>("INSERT OR REPLACE INTO test(id, name) VALUES (?,?)", database) + .write(2, "hoo"); database.applyAndUpdateSessions(); ASSERT_THAT(names(), ElementsAre("foo", "bar")); @@ -362,15 +363,16 @@ TEST_F(SqliteDatabase, SessionsCommit) TEST_F(SqliteDatabase, SessionsRollback) { database.setAttachedTables({"test"}); - Sqlite::WriteStatement("INSERT INTO test(id, name) VALUES (?,?)", database).write(1, "foo"); + Sqlite::WriteStatement<2>("INSERT INTO test(id, name) VALUES (?,?)", database).write(1, "foo"); database.unlock(); { Sqlite::ImmediateSessionTransaction transaction{database}; - Sqlite::WriteStatement("INSERT INTO test(id, name) VALUES (?,?)", database).write(2, "bar"); + Sqlite::WriteStatement<2>("INSERT INTO test(id, name) VALUES (?,?)", database).write(2, "bar"); } database.lock(); - Sqlite::WriteStatement("INSERT OR REPLACE INTO test(id, name) VALUES (?,?)", database).write(2, "hoo"); + Sqlite::WriteStatement<2>("INSERT OR REPLACE INTO test(id, name) VALUES (?,?)", database) + .write(2, "hoo"); database.applyAndUpdateSessions(); ASSERT_THAT(names(), ElementsAre("foo", "hoo")); diff --git a/tests/unit/unittest/sqlitedatabasemock.h b/tests/unit/unittest/sqlitedatabasemock.h index 3314dd3a651..4ea83a46b40 100644 --- a/tests/unit/unittest/sqlitedatabasemock.h +++ b/tests/unit/unittest/sqlitedatabasemock.h @@ -41,11 +41,12 @@ class SqliteDatabaseMock : public SqliteTransactionBackendMock, public Sqlite::DatabaseInterface { public: - template - using ReadStatement = NiceMock>; - using WriteStatement = NiceMock; - template - using ReadWriteStatement = NiceMock>; + template + using ReadStatement = NiceMock>; + template + using WriteStatement = NiceMock>; + template + using ReadWriteStatement = NiceMock>; MOCK_METHOD(void, prepare, (Utils::SmallStringView sqlStatement), ()); diff --git a/tests/unit/unittest/sqlitereadstatementmock.h b/tests/unit/unittest/sqlitereadstatementmock.h index 9bde954ac91..225c83d5c95 100644 --- a/tests/unit/unittest/sqlitereadstatementmock.h +++ b/tests/unit/unittest/sqlitereadstatementmock.h @@ -273,7 +273,7 @@ public: Utils::SmallString sqlStatement; }; -template +template class SqliteReadStatementMock : public SqliteReadStatementMockBase { public: diff --git a/tests/unit/unittest/sqlitereadwritestatementmock.h b/tests/unit/unittest/sqlitereadwritestatementmock.h index 563731c02d4..5b85a67b681 100644 --- a/tests/unit/unittest/sqlitereadwritestatementmock.h +++ b/tests/unit/unittest/sqlitereadwritestatementmock.h @@ -87,7 +87,7 @@ public: Utils::SmallString sqlStatement; }; -template +template class SqliteReadWriteStatementMock : public SqliteReadWriteStatementMockBase { public: diff --git a/tests/unit/unittest/sqlitesessions-test.cpp b/tests/unit/unittest/sqlitesessions-test.cpp index 296dd0cb743..9288f3a2a3b 100644 --- a/tests/unit/unittest/sqlitesessions-test.cpp +++ b/tests/unit/unittest/sqlitesessions-test.cpp @@ -138,18 +138,19 @@ protected: "INITIALLY DEFERRED, tag NUMERIC)", database}; Sqlite::Sessions sessions{database, "main", "testsessions"}; - Sqlite::WriteStatement insertData{"INSERT INTO data(name, number, value) VALUES (?1, ?2, ?3) " - "ON CONFLICT (name) DO UPDATE SET (number, value) = (?2, ?3)", - database}; - Sqlite::WriteStatement insertOneDatum{"INSERT INTO data(value, name) VALUES (?1, ?2) " - "ON CONFLICT (name) DO UPDATE SET (value) = (?2)", - database}; - Sqlite::WriteStatement updateNumber{"UPDATE data SET number = ?002 WHERE name=?001", database}; - Sqlite::WriteStatement updateValue{"UPDATE data SET value = ?002 WHERE name=?001", database}; - Sqlite::WriteStatement deleteData{"DELETE FROM data WHERE name=?", database}; - Sqlite::WriteStatement deleteTag{ + Sqlite::WriteStatement<3> insertData{ + "INSERT INTO data(name, number, value) VALUES (?1, ?2, ?3) " + "ON CONFLICT (name) DO UPDATE SET (number, value) = (?2, ?3)", + database}; + Sqlite::WriteStatement<2> insertOneDatum{"INSERT INTO data(value, name) VALUES (?1, ?2) " + "ON CONFLICT (name) DO UPDATE SET (value) = (?2)", + database}; + Sqlite::WriteStatement<2> updateNumber{"UPDATE data SET number = ?2 WHERE name=?1", database}; + Sqlite::WriteStatement<2> updateValue{"UPDATE data SET value = ?2 WHERE name=?1", database}; + Sqlite::WriteStatement<1> deleteData{"DELETE FROM data WHERE name=?", database}; + Sqlite::WriteStatement<1> deleteTag{ "DELETE FROM tags WHERE dataId=(SELECT id FROM data WHERE name=?)", database}; - Sqlite::WriteStatement insertTag{ + Sqlite::WriteStatement<2> insertTag{ "INSERT INTO tags(dataId, tag) VALUES ((SELECT id FROM data WHERE name=?1), ?2) ", database}; Sqlite::ReadStatement<3> selectData{"SELECT name, number, value FROM data", database}; Sqlite::ReadStatement<2> selectTags{ @@ -599,7 +600,7 @@ TEST_F(SqliteSessions, ConvertAllValueTypesInChangeSet) TEST_F(SqliteSessions, InsertOneValueChangeSet) { sessions.create(); - insertOneDatum.write("foo"); + insertOneDatum.write("foo", Sqlite::NullValue{}); sessions.commit(); auto changeSets = sessions.changeSets(); auto &&changeSet = changeSets.front(); @@ -669,7 +670,7 @@ TEST_F(SqliteSessions, EmptyChangeSet) TEST_F(SqliteSessions, AccessInsertOneValueChangeSet) { sessions.create(); - insertOneDatum.write("foo"); + insertOneDatum.write("foo", Sqlite::NullValue{}); sessions.commit(); auto changeSets = sessions.changeSets(); auto &&changeSet = changeSets.front(); diff --git a/tests/unit/unittest/sqlitestatement-test.cpp b/tests/unit/unittest/sqlitestatement-test.cpp index ea37b502221..ff5348585a4 100644 --- a/tests/unit/unittest/sqlitestatement-test.cpp +++ b/tests/unit/unittest/sqlitestatement-test.cpp @@ -54,7 +54,7 @@ using Sqlite::Value; using Sqlite::WriteStatement; template -bool compareValue(SqliteTestStatement &statement, Type value, int column) +bool compareValue(SqliteTestStatement<2, 1> &statement, Type value, int column) { if constexpr (std::is_convertible_v && !std::is_same_v) return statement.fetchLongLongValue(column) == value; @@ -77,7 +77,7 @@ MATCHER_P3(HasValues, value1, value2, rowid, { Database &database = arg.database(); - SqliteTestStatement statement("SELECT name, number FROM test WHERE rowid=?", database); + SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE rowid=?", database); statement.bind(1, rowid); statement.next(); @@ -89,7 +89,7 @@ MATCHER_P(HasNullValues, rowid, std::string(negation ? "isn't null" : "is null") { Database &database = arg.database(); - SqliteTestStatement statement("SELECT name, number FROM test WHERE rowid=?", database); + SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE rowid=?", database); statement.bind(1, rowid); statement.next(); @@ -172,7 +172,7 @@ TEST_F(SqliteStatement, ThrowsNotReadonlySqlStatementForWritableSqlStatementInRe TEST_F(SqliteStatement, CountRows) { - SqliteTestStatement statement("SELECT * FROM test", database); + SqliteTestStatement<3> statement("SELECT * FROM test", database); int nextCount = 0; while (statement.next()) ++nextCount; @@ -184,7 +184,7 @@ TEST_F(SqliteStatement, CountRows) TEST_F(SqliteStatement, Value) { - SqliteTestStatement statement("SELECT name, number, value FROM test ORDER BY name", database); + SqliteTestStatement<3> statement("SELECT name, number, value FROM test ORDER BY name", database); statement.next(); statement.next(); @@ -235,7 +235,7 @@ TEST_F(SqliteStatement, ToStringValue) TEST_F(SqliteStatement, BindNull) { database.execute("INSERT INTO test VALUES (NULL, 323, 344)"); - SqliteTestStatement statement("SELECT name, number FROM test WHERE name IS ?", database); + SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE name IS ?", database); statement.bind(1, Sqlite::NullValue{}); statement.next(); @@ -246,8 +246,7 @@ TEST_F(SqliteStatement, BindNull) TEST_F(SqliteStatement, BindString) { - - SqliteTestStatement statement("SELECT name, number FROM test WHERE name=?", database); + SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE name=?", database); statement.bind(1, Utils::SmallStringView("foo")); statement.next(); @@ -258,7 +257,7 @@ TEST_F(SqliteStatement, BindString) TEST_F(SqliteStatement, BindInteger) { - SqliteTestStatement statement("SELECT name, number FROM test WHERE number=?", database); + SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=?", database); statement.bind(1, 40); statement.next(); @@ -268,7 +267,7 @@ TEST_F(SqliteStatement, BindInteger) TEST_F(SqliteStatement, BindLongInteger) { - SqliteTestStatement statement("SELECT name, number FROM test WHERE number=?", database); + SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=?", database); statement.bind(1, int64_t(40)); statement.next(); @@ -278,7 +277,7 @@ TEST_F(SqliteStatement, BindLongInteger) TEST_F(SqliteStatement, BindDouble) { - SqliteTestStatement statement("SELECT name, number FROM test WHERE number=?", database); + SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=?", database); statement.bind(1, 23.3); statement.next(); @@ -288,7 +287,7 @@ TEST_F(SqliteStatement, BindDouble) TEST_F(SqliteStatement, BindPointer) { - SqliteTestStatement statement("SELECT value FROM carray(?, 5, 'int64')", database); + SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?, 5, 'int64')", database); std::vector values{1, 1, 2, 3, 5}; statement.bind(1, values.data()); @@ -299,7 +298,7 @@ TEST_F(SqliteStatement, BindPointer) TEST_F(SqliteStatement, BindIntCarray) { - SqliteTestStatement statement("SELECT value FROM carray(?)", database); + SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database); std::vector values{3, 10, 20, 33, 55}; statement.bind(1, values); @@ -313,7 +312,7 @@ TEST_F(SqliteStatement, BindIntCarray) TEST_F(SqliteStatement, BindLongLongCarray) { - SqliteTestStatement statement("SELECT value FROM carray(?)", database); + SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database); std::vector values{3, 10, 20, 33, 55}; statement.bind(1, values); @@ -327,7 +326,7 @@ TEST_F(SqliteStatement, BindLongLongCarray) TEST_F(SqliteStatement, BindDoubleCarray) { - SqliteTestStatement statement("SELECT value FROM carray(?)", database); + SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database); std::vector values{3.3, 10.2, 20.54, 33.21, 55}; statement.bind(1, values); @@ -341,7 +340,7 @@ TEST_F(SqliteStatement, BindDoubleCarray) TEST_F(SqliteStatement, BindTextCarray) { - SqliteTestStatement statement("SELECT value FROM carray(?)", database); + SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database); std::vector values{"yi", "er", "san", "se", "wu"}; statement.bind(1, values); @@ -355,7 +354,7 @@ TEST_F(SqliteStatement, BindTextCarray) TEST_F(SqliteStatement, BindBlob) { - SqliteTestStatement statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database); + SqliteTestStatement<1, 1> statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database); const unsigned char chars[] = "aaafdfdlll"; auto bytePointer = reinterpret_cast(chars); Sqlite::BlobView bytes{bytePointer, sizeof(chars) - 1}; @@ -368,7 +367,7 @@ TEST_F(SqliteStatement, BindBlob) TEST_F(SqliteStatement, BindEmptyBlob) { - SqliteTestStatement statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database); + SqliteTestStatement<1, 1> statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database); Sqlite::BlobView bytes; statement.bind(1, bytes); @@ -379,56 +378,56 @@ TEST_F(SqliteStatement, BindEmptyBlob) TEST_F(SqliteStatement, BindIndexIsZeroIsThrowingBindingIndexIsOutOfBoundInt) { - SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database); + SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database); ASSERT_THROW(statement.bind(0, 40), Sqlite::BindingIndexIsOutOfRange); } TEST_F(SqliteStatement, BindIndexIsZeroIsThrowingBindingIndexIsOutOfBoundNull) { - SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database); + SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database); ASSERT_THROW(statement.bind(0, Sqlite::NullValue{}), Sqlite::BindingIndexIsOutOfRange); } TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundLongLong) { - SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database); + SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database); ASSERT_THROW(statement.bind(2, 40LL), Sqlite::BindingIndexIsOutOfRange); } TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundStringView) { - SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database); + SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database); ASSERT_THROW(statement.bind(2, "foo"), Sqlite::BindingIndexIsOutOfRange); } TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundStringFloat) { - SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database); + SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database); ASSERT_THROW(statement.bind(2, 2.), Sqlite::BindingIndexIsOutOfRange); } TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundPointer) { - SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database); + SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database); ASSERT_THROW(statement.bind(2, nullptr), Sqlite::BindingIndexIsOutOfRange); } TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundValue) { - SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database); + SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database); ASSERT_THROW(statement.bind(2, Sqlite::Value{1}), Sqlite::BindingIndexIsOutOfRange); } TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundBlob) { - SqliteTestStatement statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database); + SqliteTestStatement<1, 1> statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database); Sqlite::BlobView bytes{QByteArray{"XXX"}}; ASSERT_THROW(statement.bind(2, bytes), Sqlite::BindingIndexIsOutOfRange); @@ -436,7 +435,7 @@ TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundBlob TEST_F(SqliteStatement, BindValues) { - SqliteTestStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); + SqliteTestStatement<0, 3> statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); statement.bindValues("see", 7.23, 1); statement.execute(); @@ -446,7 +445,7 @@ TEST_F(SqliteStatement, BindValues) TEST_F(SqliteStatement, BindNullValues) { - SqliteTestStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); + SqliteTestStatement<0, 3> statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); statement.bindValues(Sqlite::NullValue{}, Sqlite::Value{}, 1); statement.execute(); @@ -456,7 +455,7 @@ TEST_F(SqliteStatement, BindNullValues) TEST_F(SqliteStatement, WriteValues) { - WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); + WriteStatement<3> statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); statement.write("see", 7.23, 1); @@ -465,58 +464,57 @@ TEST_F(SqliteStatement, WriteValues) TEST_F(SqliteStatement, WritePointerValues) { - SqliteTestStatement statement("SELECT value FROM carray(?, ?, 'int64')", database); + SqliteTestStatement<1, 2> statement("SELECT value FROM carray(?, ?, 'int64')", database); std::vector values{1, 1, 2, 3, 5}; - statement.write(values.data(), int(values.size())); + auto results = statement.values(5, values.data(), int(values.size())); - ASSERT_THAT(statement.template values(5), ElementsAre(1, 1, 2, 3, 5)); + ASSERT_THAT(results, ElementsAre(1, 1, 2, 3, 5)); } TEST_F(SqliteStatement, WriteIntCarrayValues) { - SqliteTestStatement statement("SELECT value FROM carray(?)", database); + SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database); std::vector values{3, 10, 20, 33, 55}; - statement.write(Utils::span(values)); + auto results = statement.values(5, Utils::span(values)); - ASSERT_THAT(statement.template values(5), ElementsAre(3, 10, 20, 33, 55)); + ASSERT_THAT(results, ElementsAre(3, 10, 20, 33, 55)); } TEST_F(SqliteStatement, WriteLongLongCarrayValues) { - SqliteTestStatement statement("SELECT value FROM carray(?)", database); + SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database); std::vector values{3, 10, 20, 33, 55}; - statement.write(Utils::span(values)); + auto results = statement.values(5, Utils::span(values)); - ASSERT_THAT(statement.template values(5), ElementsAre(3, 10, 20, 33, 55)); + ASSERT_THAT(results, ElementsAre(3, 10, 20, 33, 55)); } TEST_F(SqliteStatement, WriteDoubleCarrayValues) { - SqliteTestStatement statement("SELECT value FROM carray(?)", database); + SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database); std::vector values{3.3, 10.2, 20.54, 33.21, 55}; - statement.write(Utils::span(values)); + auto results = statement.values(5, Utils::span(values)); - ASSERT_THAT(statement.template values(5), ElementsAre(3.3, 10.2, 20.54, 33.21, 55)); + ASSERT_THAT(results, ElementsAre(3.3, 10.2, 20.54, 33.21, 55)); } TEST_F(SqliteStatement, WriteTextCarrayValues) { - SqliteTestStatement statement("SELECT value FROM carray(?)", database); + SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database); std::vector values{"yi", "er", "san", "se", "wu"}; - statement.write(Utils::span(values)); + auto results = statement.values(5, Utils::span(values)); - ASSERT_THAT(statement.template values(5), - ElementsAre("yi", "er", "san", "se", "wu")); + ASSERT_THAT(results, ElementsAre("yi", "er", "san", "se", "wu")); } TEST_F(SqliteStatement, WriteNullValues) { - WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); + WriteStatement<3> statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); statement.write(1, 1, 1); statement.write(Sqlite::NullValue{}, Sqlite::Value{}, 1); @@ -526,7 +524,7 @@ TEST_F(SqliteStatement, WriteNullValues) TEST_F(SqliteStatement, WriteSqliteIntegerValue) { - WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); + WriteStatement<3> statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); statement.write(1, 1, 1); statement.write("see", Sqlite::Value{33}, 1); @@ -536,7 +534,7 @@ TEST_F(SqliteStatement, WriteSqliteIntegerValue) TEST_F(SqliteStatement, WriteSqliteDoubeValue) { - WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); + WriteStatement<3> statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); statement.write("see", Value{7.23}, Value{1}); @@ -545,7 +543,7 @@ TEST_F(SqliteStatement, WriteSqliteDoubeValue) TEST_F(SqliteStatement, WriteSqliteStringValue) { - WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); + WriteStatement<3> statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); statement.write("see", Value{"foo"}, Value{1}); @@ -554,8 +552,8 @@ TEST_F(SqliteStatement, WriteSqliteStringValue) TEST_F(SqliteStatement, WriteSqliteBlobValue) { - SqliteTestStatement statement("INSERT INTO test VALUES ('blob', 40, ?)", database); - SqliteTestStatement readStatement("SELECT value FROM test WHERE name = 'blob'", database); + SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('blob', 40, ?)", database); + SqliteTestStatement<1, 0> readStatement("SELECT value FROM test WHERE name = 'blob'", database); const unsigned char chars[] = "aaafdfdlll"; auto bytePointer = reinterpret_cast(chars); Sqlite::BlobView bytes{bytePointer, sizeof(chars) - 1}; @@ -568,7 +566,7 @@ TEST_F(SqliteStatement, WriteSqliteBlobValue) TEST_F(SqliteStatement, WriteNullValueView) { - WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); + WriteStatement<3> statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); statement.write(1, 1, 1); statement.write(Sqlite::NullValue{}, Sqlite::ValueView::create(Sqlite::NullValue{}), 1); @@ -578,7 +576,7 @@ TEST_F(SqliteStatement, WriteNullValueView) TEST_F(SqliteStatement, WriteSqliteIntegerValueView) { - WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); + WriteStatement<3> statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); statement.write(1, 1, 1); statement.write("see", Sqlite::ValueView::create(33), 1); @@ -588,7 +586,7 @@ TEST_F(SqliteStatement, WriteSqliteIntegerValueView) TEST_F(SqliteStatement, WriteSqliteDoubeValueView) { - WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); + WriteStatement<3> statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); statement.write("see", Sqlite::ValueView::create(7.23), 1); @@ -597,7 +595,7 @@ TEST_F(SqliteStatement, WriteSqliteDoubeValueView) TEST_F(SqliteStatement, WriteSqliteStringValueView) { - WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); + WriteStatement<3> statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); statement.write("see", Sqlite::ValueView::create("foo"), 1); @@ -606,8 +604,8 @@ TEST_F(SqliteStatement, WriteSqliteStringValueView) TEST_F(SqliteStatement, WriteSqliteBlobValueView) { - SqliteTestStatement statement("INSERT INTO test VALUES ('blob', 40, ?)", database); - SqliteTestStatement readStatement("SELECT value FROM test WHERE name = 'blob'", database); + SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('blob', 40, ?)", database); + SqliteTestStatement<1, 0> readStatement("SELECT value FROM test WHERE name = 'blob'", database); const unsigned char chars[] = "aaafdfdlll"; auto bytePointer = reinterpret_cast(chars); Sqlite::BlobView bytes{bytePointer, sizeof(chars) - 1}; @@ -620,7 +618,7 @@ TEST_F(SqliteStatement, WriteSqliteBlobValueView) TEST_F(SqliteStatement, WriteEmptyBlobs) { - SqliteTestStatement statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database); + SqliteTestStatement<1, 1> statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database); Sqlite::BlobView bytes; @@ -631,8 +629,8 @@ TEST_F(SqliteStatement, WriteEmptyBlobs) TEST_F(SqliteStatement, EmptyBlobsAreNull) { - SqliteTestStatement statement("WITH T(blob) AS (VALUES (?)) SELECT ifnull(blob, 1) FROM T", - database); + SqliteTestStatement<1, 1> statement( + "WITH T(blob) AS (VALUES (?)) SELECT ifnull(blob, 1) FROM T", database); Sqlite::BlobView bytes; @@ -643,8 +641,8 @@ TEST_F(SqliteStatement, EmptyBlobsAreNull) TEST_F(SqliteStatement, WriteBlobs) { - SqliteTestStatement statement("INSERT INTO test VALUES ('blob', 40, ?)", database); - SqliteTestStatement readStatement("SELECT value FROM test WHERE name = 'blob'", database); + SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('blob', 40, ?)", database); + SqliteTestStatement<1, 0> readStatement("SELECT value FROM test WHERE name = 'blob'", database); const unsigned char chars[] = "aaafdfdlll"; auto bytePointer = reinterpret_cast(chars); Sqlite::BlobView bytes{bytePointer, sizeof(chars) - 1}; @@ -918,7 +916,7 @@ TEST_F(SqliteStatement, GetStructRangeWithTransactionWithoutArguments) TEST_F(SqliteStatement, GetValuesForSingleOutputWithBindingMultipleTimes) { - ReadStatement<1> statement("SELECT name FROM test WHERE number=?", database); + ReadStatement<1, 1> statement("SELECT name FROM test WHERE number=?", database); statement.values(3, 40); std::vector values = statement.values(3, 40); @@ -928,7 +926,7 @@ TEST_F(SqliteStatement, GetValuesForSingleOutputWithBindingMultipleTimes) TEST_F(SqliteStatement, GetRangeForSingleOutputWithBindingMultipleTimes) { - ReadStatement<1> statement("SELECT name FROM test WHERE number=?", database); + ReadStatement<1, 1> statement("SELECT name FROM test WHERE number=?", database); statement.values(3, 40); auto range = statement.range(40); @@ -939,7 +937,7 @@ TEST_F(SqliteStatement, GetRangeForSingleOutputWithBindingMultipleTimes) TEST_F(SqliteStatement, GetRangeWithTransactionForSingleOutputWithBindingMultipleTimes) { - ReadStatement<1> statement("SELECT name FROM test WHERE number=?", database); + ReadStatement<1, 1> statement("SELECT name FROM test WHERE number=?", database); statement.values(3, 40); database.unlock(); @@ -953,7 +951,7 @@ TEST_F(SqliteStatement, GetRangeWithTransactionForSingleOutputWithBindingMultipl TEST_F(SqliteStatement, GetValuesForMultipleOutputValuesAndMultipleQueryValue) { using Tuple = std::tuple; - ReadStatement<3> statement( + ReadStatement<3, 3> statement( "SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database); auto values = statement.values(3, "bar", "blah", 1); @@ -964,7 +962,7 @@ TEST_F(SqliteStatement, GetValuesForMultipleOutputValuesAndMultipleQueryValue) TEST_F(SqliteStatement, GetRangeForMultipleOutputValuesAndMultipleQueryValue) { using Tuple = std::tuple; - ReadStatement<3> statement( + ReadStatement<3, 3> statement( "SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database); auto range = statement.range("bar", "blah", 1); @@ -976,7 +974,7 @@ TEST_F(SqliteStatement, GetRangeForMultipleOutputValuesAndMultipleQueryValue) TEST_F(SqliteStatement, GetRangeWithTransactionForMultipleOutputValuesAndMultipleQueryValue) { using Tuple = std::tuple; - ReadStatement<3> statement( + ReadStatement<3, 3> statement( "SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database); database.unlock(); @@ -989,8 +987,8 @@ TEST_F(SqliteStatement, GetRangeWithTransactionForMultipleOutputValuesAndMultipl TEST_F(SqliteStatement, CallGetValuesForMultipleOutputValuesAndMultipleQueryValueMultipleTimes) { using Tuple = std::tuple; - ReadStatement<3> statement("SELECT name, number, value FROM test WHERE name=? AND number=?", - database); + ReadStatement<3, 2> statement("SELECT name, number, value FROM test WHERE name=? AND number=?", + database); statement.values(3, "bar", "blah"); auto values = statement.values(3, "bar", "blah"); @@ -1001,8 +999,8 @@ TEST_F(SqliteStatement, CallGetValuesForMultipleOutputValuesAndMultipleQueryValu TEST_F(SqliteStatement, CallGetRangeForMultipleOutputValuesAndMultipleQueryValueMultipleTimes) { using Tuple = std::tuple; - ReadStatement<3> statement("SELECT name, number, value FROM test WHERE name=? AND number=?", - database); + ReadStatement<3, 2> statement("SELECT name, number, value FROM test WHERE name=? AND number=?", + database); { auto range = statement.range("bar", "blah"); std::vector values1{range.begin(), range.end()}; @@ -1018,8 +1016,8 @@ TEST_F(SqliteStatement, CallGetRangeWithTransactionForMultipleOutputValuesAndMultipleQueryValueMultipleTimes) { using Tuple = std::tuple; - ReadStatement<3> statement("SELECT name, number, value FROM test WHERE name=? AND number=?", - database); + ReadStatement<3, 2> statement("SELECT name, number, value FROM test WHERE name=? AND number=?", + database); database.unlock(); std::vector values1 = toValues(statement.rangeWithTransaction("bar", "blah")); @@ -1031,7 +1029,7 @@ TEST_F(SqliteStatement, TEST_F(SqliteStatement, GetStructOutputValuesAndMultipleQueryValue) { - ReadStatement<3> statement( + ReadStatement<3, 3> statement( "SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database); auto values = statement.values(3, "bar", "blah", 1); @@ -1081,8 +1079,8 @@ TEST_F(SqliteStatement, GetEmptyOptionalBlobValueForText) TEST_F(SqliteStatement, GetOptionalSingleValueAndMultipleQueryValue) { - ReadStatement<1> statement("SELECT name FROM test WHERE name=? AND number=? AND value=?", - database); + ReadStatement<1, 3> statement("SELECT name FROM test WHERE name=? AND number=? AND value=?", + database); auto value = statement.optionalValue("bar", "blah", 1); @@ -1091,7 +1089,7 @@ TEST_F(SqliteStatement, GetOptionalSingleValueAndMultipleQueryValue) TEST_F(SqliteStatement, GetOptionalOutputValueAndMultipleQueryValue) { - ReadStatement<3> statement( + ReadStatement<3, 3> statement( "SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database); auto value = statement.optionalValue("bar", "blah", 1); @@ -1102,7 +1100,7 @@ TEST_F(SqliteStatement, GetOptionalOutputValueAndMultipleQueryValue) TEST_F(SqliteStatement, GetOptionalTupleValueAndMultipleQueryValue) { using Tuple = std::tuple; - ReadStatement<3> statement( + ReadStatement<3, 3> statement( "SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database); auto value = statement.optionalValue("bar", "blah", 1); @@ -1112,7 +1110,7 @@ TEST_F(SqliteStatement, GetOptionalTupleValueAndMultipleQueryValue) TEST_F(SqliteStatement, GetOptionalValueCallsReset) { - MockSqliteStatement mockStatement{databaseMock}; + MockSqliteStatement<1, 1> mockStatement{databaseMock}; EXPECT_CALL(mockStatement, reset()); @@ -1121,7 +1119,7 @@ TEST_F(SqliteStatement, GetOptionalValueCallsReset) TEST_F(SqliteStatement, GetOptionalValueCallsResetIfExceptionIsThrown) { - MockSqliteStatement mockStatement{databaseMock}; + MockSqliteStatement<1, 1> mockStatement{databaseMock}; ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); EXPECT_CALL(mockStatement, reset()); @@ -1131,8 +1129,8 @@ TEST_F(SqliteStatement, GetOptionalValueCallsResetIfExceptionIsThrown) TEST_F(SqliteStatement, GetSingleValueAndMultipleQueryValue) { - ReadStatement<1> statement("SELECT name FROM test WHERE name=? AND number=? AND value=?", - database); + ReadStatement<1, 3> statement("SELECT name FROM test WHERE name=? AND number=? AND value=?", + database); auto value = statement.value("bar", "blah", 1); @@ -1141,7 +1139,7 @@ TEST_F(SqliteStatement, GetSingleValueAndMultipleQueryValue) TEST_F(SqliteStatement, GetOutputValueAndMultipleQueryValue) { - ReadStatement<3> statement( + ReadStatement<3, 3> statement( "SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database); auto value = statement.value("bar", "blah", 1); @@ -1152,7 +1150,7 @@ TEST_F(SqliteStatement, GetOutputValueAndMultipleQueryValue) TEST_F(SqliteStatement, GetTupleValueAndMultipleQueryValue) { using Tuple = std::tuple; - ReadStatement<3> statement( + ReadStatement<3, 3> statement( "SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database); auto value = statement.value("bar", "blah", 1); @@ -1166,7 +1164,7 @@ TEST_F(SqliteStatement, GetValueCallsReset) { int x = 0; }; - MockSqliteStatement mockStatement{databaseMock}; + MockSqliteStatement<1, 1> mockStatement{databaseMock}; EXPECT_CALL(mockStatement, reset()); @@ -1179,7 +1177,7 @@ TEST_F(SqliteStatement, GetValueCallsResetIfExceptionIsThrown) { int x = 0; }; - MockSqliteStatement mockStatement{databaseMock}; + MockSqliteStatement<1, 1> mockStatement{databaseMock}; ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); EXPECT_CALL(mockStatement, reset()); @@ -1189,7 +1187,7 @@ TEST_F(SqliteStatement, GetValueCallsResetIfExceptionIsThrown) TEST_F(SqliteStatement, GetValuesWithoutArgumentsCallsReset) { - MockSqliteStatement mockStatement{databaseMock}; + MockSqliteStatement<1, 0> mockStatement{databaseMock}; EXPECT_CALL(mockStatement, reset()); @@ -1198,7 +1196,7 @@ TEST_F(SqliteStatement, GetValuesWithoutArgumentsCallsReset) TEST_F(SqliteStatement, GetRangeWithoutArgumentsCallsReset) { - MockSqliteStatement mockStatement{databaseMock}; + MockSqliteStatement<1, 0> mockStatement{databaseMock}; EXPECT_CALL(mockStatement, reset()); @@ -1208,7 +1206,7 @@ TEST_F(SqliteStatement, GetRangeWithoutArgumentsCallsReset) TEST_F(SqliteStatement, GetRangeWithTransactionWithoutArgumentsCalls) { InSequence s; - MockSqliteStatement mockStatement{databaseMock}; + MockSqliteStatement<1, 0> mockStatement{databaseMock}; EXPECT_CALL(databaseMock, lock()); EXPECT_CALL(databaseMock, deferredBegin()); @@ -1221,7 +1219,7 @@ TEST_F(SqliteStatement, GetRangeWithTransactionWithoutArgumentsCalls) TEST_F(SqliteStatement, GetValuesWithoutArgumentsCallsResetIfExceptionIsThrown) { - MockSqliteStatement mockStatement{databaseMock}; + MockSqliteStatement<1, 0> mockStatement{databaseMock}; ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); EXPECT_CALL(mockStatement, reset()); @@ -1231,7 +1229,7 @@ TEST_F(SqliteStatement, GetValuesWithoutArgumentsCallsResetIfExceptionIsThrown) TEST_F(SqliteStatement, GetRangeWithoutArgumentsCallsResetIfExceptionIsThrown) { - MockSqliteStatement mockStatement{databaseMock}; + MockSqliteStatement<1, 0> mockStatement{databaseMock}; ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); auto range = mockStatement.range(); @@ -1243,7 +1241,7 @@ TEST_F(SqliteStatement, GetRangeWithoutArgumentsCallsResetIfExceptionIsThrown) TEST_F(SqliteStatement, GetRangeWithTransactionWithoutArgumentsCallsResetIfExceptionIsThrown) { InSequence s; - MockSqliteStatement mockStatement{databaseMock}; + MockSqliteStatement<1, 0> mockStatement{databaseMock}; ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); EXPECT_CALL(databaseMock, lock()); @@ -1262,7 +1260,7 @@ TEST_F(SqliteStatement, GetRangeWithTransactionWithoutArgumentsCallsResetIfExcep TEST_F(SqliteStatement, GetValuesWithSimpleArgumentsCallsReset) { - MockSqliteStatement mockStatement{databaseMock}; + MockSqliteStatement<1, 2> mockStatement{databaseMock}; EXPECT_CALL(mockStatement, reset()); @@ -1271,7 +1269,7 @@ TEST_F(SqliteStatement, GetValuesWithSimpleArgumentsCallsReset) TEST_F(SqliteStatement, GetValuesWithSimpleArgumentsCallsResetIfExceptionIsThrown) { - MockSqliteStatement mockStatement{databaseMock}; + MockSqliteStatement<1, 2> mockStatement{databaseMock}; ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); EXPECT_CALL(mockStatement, reset()); @@ -1281,7 +1279,7 @@ TEST_F(SqliteStatement, GetValuesWithSimpleArgumentsCallsResetIfExceptionIsThrow TEST_F(SqliteStatement, ResetIfWriteIsThrowingException) { - MockSqliteStatement mockStatement{databaseMock}; + MockSqliteStatement<1, 1> mockStatement{databaseMock}; EXPECT_CALL(mockStatement, bind(1, TypedEq("bar"))) .WillOnce(Throw(Sqlite::StatementIsBusy(""))); @@ -1292,7 +1290,7 @@ TEST_F(SqliteStatement, ResetIfWriteIsThrowingException) TEST_F(SqliteStatement, ResetIfExecuteThrowsException) { - MockSqliteStatement mockStatement{databaseMock}; + MockSqliteStatement<1, 0> mockStatement{databaseMock}; EXPECT_CALL(mockStatement, next()).WillOnce(Throw(Sqlite::StatementIsBusy(""))); EXPECT_CALL(mockStatement, reset()); @@ -1300,20 +1298,34 @@ TEST_F(SqliteStatement, ResetIfExecuteThrowsException) ASSERT_ANY_THROW(mockStatement.execute()); } -TEST_F(SqliteStatement, ReadStatementThrowsColumnCountDoesNotMatch) +TEST_F(SqliteStatement, ReadStatementThrowsWrongColumnCount) { - MockFunction callbackMock; - ASSERT_THROW(ReadStatement<1> statement("SELECT name, number FROM test", database), - Sqlite::ColumnCountDoesNotMatch); + Sqlite::WrongColumnCount); } -TEST_F(SqliteStatement, ReadWriteStatementThrowsColumnCountDoesNotMatch) +TEST_F(SqliteStatement, ReadWriteStatementThrowsWrongColumnCount) { - MockFunction callbackMock; - ASSERT_THROW(ReadWriteStatement<1> statement("SELECT name, number FROM test", database), - Sqlite::ColumnCountDoesNotMatch); + Sqlite::WrongColumnCount); +} + +TEST_F(SqliteStatement, WriteStatementThrowsWrongBindingParameterCount) +{ + ASSERT_THROW(WriteStatement<1>("INSERT INTO test(name, number) VALUES(?1, ?2)", database), + Sqlite::WrongBindingParameterCount); +} + +TEST_F(SqliteStatement, ReadWriteStatementThrowsWrongBindingParameterCount) +{ + ASSERT_THROW((ReadWriteStatement<0, 1>("INSERT INTO test(name, number) VALUES(?1, ?2)", database)), + Sqlite::WrongBindingParameterCount); +} + +TEST_F(SqliteStatement, ReadStatementThrowsWrongBindingParameterCount) +{ + ASSERT_THROW((ReadStatement<2, 0>("SELECT name, number FROM test WHERE name=?", database)), + Sqlite::WrongBindingParameterCount); } TEST_F(SqliteStatement, ReadCallback) @@ -1331,7 +1343,7 @@ TEST_F(SqliteStatement, ReadCallback) TEST_F(SqliteStatement, ReadCallbackCalledWithArguments) { MockFunction callbackMock; - ReadStatement<2> statement("SELECT name, value FROM test WHERE value=?", database); + ReadStatement<2, 1> statement("SELECT name, value FROM test WHERE value=?", database); EXPECT_CALL(callbackMock, Call(Eq("foo"), Eq(2))); @@ -1404,7 +1416,7 @@ TEST_F(SqliteStatement, ReadToContainer) TEST_F(SqliteStatement, ReadToContainerCallCallbackWithArguments) { std::deque values; - ReadStatement<1> statement("SELECT number FROM test WHERE value=?", database); + ReadStatement<1, 1> statement("SELECT number FROM test WHERE value=?", database); statement.readTo(values, 2); @@ -1444,8 +1456,8 @@ TEST_F(SqliteStatement, ReadToCallsResetIfExceptionIsThrown) TEST_F(SqliteStatement, ReadStatementValuesWithTransactions) { using Tuple = std::tuple; - ReadStatement<3> statement("SELECT name, number, value FROM test WHERE name=? AND number=?", - database); + ReadStatement<3, 2> statement("SELECT name, number, value FROM test WHERE name=? AND number=?", + database); database.unlock(); std::vector values = statement.valuesWithTransaction(1024, "bar", "blah"); @@ -1457,8 +1469,8 @@ TEST_F(SqliteStatement, ReadStatementValuesWithTransactions) TEST_F(SqliteStatement, ReadStatementValueWithTransactions) { using Tuple = std::tuple; - ReadStatement<3> statement("SELECT name, number, value FROM test WHERE name=? AND number=?", - database); + ReadStatement<3, 2> statement("SELECT name, number, value FROM test WHERE name=? AND number=?", + database); database.unlock(); auto value = statement.valueWithTransaction("bar", "blah"); @@ -1470,8 +1482,8 @@ TEST_F(SqliteStatement, ReadStatementValueWithTransactions) TEST_F(SqliteStatement, ReadStatementOptionalValueWithTransactions) { using Tuple = std::tuple; - ReadStatement<3> statement("SELECT name, number, value FROM test WHERE name=? AND number=?", - database); + ReadStatement<3, 2> statement("SELECT name, number, value FROM test WHERE name=? AND number=?", + database); database.unlock(); auto value = statement.optionalValueWithTransaction("bar", "blah"); @@ -1483,8 +1495,8 @@ TEST_F(SqliteStatement, ReadStatementOptionalValueWithTransactions) TEST_F(SqliteStatement, ReadStatementReadCallbackWithTransactions) { MockFunction callbackMock; - ReadStatement<3> statement("SELECT name, number, value FROM test WHERE name=? AND number=?", - database); + ReadStatement<3, 2> statement("SELECT name, number, value FROM test WHERE name=? AND number=?", + database); database.unlock(); EXPECT_CALL(callbackMock, Call(Eq("bar"), Eq("blah"), Eq(1))); @@ -1496,8 +1508,8 @@ TEST_F(SqliteStatement, ReadStatementReadCallbackWithTransactions) TEST_F(SqliteStatement, ReadStatementReadToWithTransactions) { using Tuple = std::tuple; - ReadStatement<3> statement("SELECT name, number, value FROM test WHERE name=? AND number=?", - database); + ReadStatement<3, 2> statement("SELECT name, number, value FROM test WHERE name=? AND number=?", + database); std::vector values; database.unlock(); @@ -1510,7 +1522,7 @@ TEST_F(SqliteStatement, ReadStatementReadToWithTransactions) TEST_F(SqliteStatement, ReadWriteStatementValuesWithTransactions) { using Tuple = std::tuple; - ReadWriteStatement<3> statement( + ReadWriteStatement<3, 2> statement( "SELECT name, number, value FROM test WHERE name=? AND number=?", database); database.unlock(); @@ -1523,7 +1535,7 @@ TEST_F(SqliteStatement, ReadWriteStatementValuesWithTransactions) TEST_F(SqliteStatement, ReadWriteStatementValueWithTransactions) { using Tuple = std::tuple; - ReadWriteStatement<3> statement( + ReadWriteStatement<3, 2> statement( "SELECT name, number, value FROM test WHERE name=? AND number=?", database); database.unlock(); @@ -1536,7 +1548,7 @@ TEST_F(SqliteStatement, ReadWriteStatementValueWithTransactions) TEST_F(SqliteStatement, ReadWriteStatementOptionalValueWithTransactions) { using Tuple = std::tuple; - ReadWriteStatement<3> statement( + ReadWriteStatement<3, 2> statement( "SELECT name, number, value FROM test WHERE name=? AND number=?", database); database.unlock(); @@ -1549,7 +1561,7 @@ TEST_F(SqliteStatement, ReadWriteStatementOptionalValueWithTransactions) TEST_F(SqliteStatement, ReadWriteStatementReadCallbackWithTransactions) { MockFunction callbackMock; - ReadWriteStatement<3> statement( + ReadWriteStatement<3, 2> statement( "SELECT name, number, value FROM test WHERE name=? AND number=?", database); database.unlock(); @@ -1562,7 +1574,7 @@ TEST_F(SqliteStatement, ReadWriteStatementReadCallbackWithTransactions) TEST_F(SqliteStatement, ReadWriteStatementReadToWithTransactions) { using Tuple = std::tuple; - ReadWriteStatement<3> statement( + ReadWriteStatement<3, 2> statement( "SELECT name, number, value FROM test WHERE name=? AND number=?", database); std::vector values; database.unlock(); diff --git a/tests/unit/unittest/sqliteteststatement.h b/tests/unit/unittest/sqliteteststatement.h index f2fe6ba2959..f90f319824c 100644 --- a/tests/unit/unittest/sqliteteststatement.h +++ b/tests/unit/unittest/sqliteteststatement.h @@ -26,10 +26,11 @@ #pragma once #include - -class SqliteTestStatement : public Sqlite::StatementImplementation +template +class SqliteTestStatement + : public Sqlite::StatementImplementation { - using Base = Sqlite::StatementImplementation; + using Base = Sqlite::StatementImplementation; public: explicit SqliteTestStatement(Utils::SmallStringView sqlStatement, Sqlite::Database &database) diff --git a/tests/unit/unittest/sqlitewritestatementmock.cpp b/tests/unit/unittest/sqlitewritestatementmock.cpp index a3612833b2e..0cfb6a677f2 100644 --- a/tests/unit/unittest/sqlitewritestatementmock.cpp +++ b/tests/unit/unittest/sqlitewritestatementmock.cpp @@ -27,8 +27,8 @@ #include "sqlitedatabasemock.h" -SqliteWriteStatementMock::SqliteWriteStatementMock(Utils::SmallStringView sqlStatement, - SqliteDatabaseMock &database) +SqliteWriteStatementMockBase::SqliteWriteStatementMockBase(Utils::SmallStringView sqlStatement, + SqliteDatabaseMock &database) : sqlStatement(sqlStatement) { database.prepare(sqlStatement); diff --git a/tests/unit/unittest/sqlitewritestatementmock.h b/tests/unit/unittest/sqlitewritestatementmock.h index 9031da67bbe..5dd939e7448 100644 --- a/tests/unit/unittest/sqlitewritestatementmock.h +++ b/tests/unit/unittest/sqlitewritestatementmock.h @@ -32,11 +32,11 @@ class SqliteDatabaseMock; -class SqliteWriteStatementMock +class SqliteWriteStatementMockBase { public: - SqliteWriteStatementMock() = default; - SqliteWriteStatementMock(Utils::SmallStringView sqlStatement, SqliteDatabaseMock &database); + SqliteWriteStatementMockBase() = default; + SqliteWriteStatementMockBase(Utils::SmallStringView sqlStatement, SqliteDatabaseMock &database); MOCK_METHOD(void, execute, (), ()); @@ -119,3 +119,10 @@ public: Utils::SmallString sqlStatement; }; + +template +class SqliteWriteStatementMock : public SqliteWriteStatementMockBase +{ +public: + using SqliteWriteStatementMockBase::SqliteWriteStatementMockBase; +};